Dominando a Análise de Argumentos Bash para Scripts Poderosos
Analise argumentos Bash com parâmetros posicionais, getopts, loops de opções longas, valores padrão e erros de uso claros.
Dominando a Análise de Argumentos Bash para Scripts Poderosos
Os argumentos de linha de comando são o que tornam seus scripts Bash flexíveis. Quando a análise de argumentos Bash é fraca, você acaba editando variáveis dentro do script toda vez que precisa de um arquivo, host ou modo diferente.
Este guia mostra como lidar com argumentos posicionais, opções curtas com getopts e opções longas com um loop while/case. O objetivo é um script que rejeita entradas ruins cedo e informa exatamente como executá-lo.
O Básico: Argumentos Posicionais
Antes de lidar com flags e opções nomeadas, é crucial entender como o Bash lida com argumentos simples e sequenciais.
| Variável | Descrição | Exemplo se chamado como ./script.sh foo bar |
|---|---|---|
$0 |
O nome do script em si | ./script.sh |
$1, $2, ... |
O primeiro, segundo, etc., argumento posicional | foo, bar |
$# |
A contagem de argumentos posicionais | 2 |
$@ |
Todos os argumentos posicionais, tratados como strings separadas | foo bar |
$* |
Todos os argumentos posicionais, tratados como uma única string | foo bar |
Exemplo: Verificação Posicional Simples
#!/bin/bash
if [ "$#" -ne 2 ]; then
echo "Uso: $0 <arquivo_origem> <diretorio_destino>"
exit 1
fi
ORIGEM="$1"
DESTINO="$2"
echo "Copiando $ORIGEM para $DESTINO..."
# cp "$ORIGEM" "$DESTINO"
Análise Padrão com getopts para Opções Curtas
Para scripts profissionais que exigem opções como -v (verboso) ou -f <arquivo>, o utilitário embutido getopts é o método canônico e mais confiável em Bash puro. Ele é projetado especificamente para opções curtas (um único caractere).
Como getopts Funciona
getopts lê opções sequencialmente, definindo a variável designada (geralmente OPT) para a opção encontrada e colocando o valor de qualquer argumento (se necessário) na variável OPTARG.
- String de Opção (OPTSTRING): Define opções válidas. Se uma opção requer um argumento (por exemplo,
-f nome_arquivo), siga o caractere com dois pontos (:). Exemplo:vho:permite-v,-he-oque requer um valor. OPTIND: Um índice interno do Bash que rastreia o próximo argumento a ser processado. Ele deve ser inicializado como 1 (que é o padrão, mas às vezes redefinido em scripts complexos).
Modelo Prático de getopts
Este modelo lida com três opções: -v (flag), -h (flag) e -f (opção que requer um valor).
#!/bin/bash
# --- Padrões ---
VERBOSO=0
NOME_ARQUIVO="padrao.txt"
# --- Função de Uso ---
uso() {
echo "Uso: $0 [-v] [-h] [-f <arquivo>] <entrada>"
exit 1
}
# --- Loop de Análise de Argumentos ---
while getopts ":vhf:" OPT; do
case "$OPT" in
v)
VERBOSO=1
echo "Modo verboso ativado."
;;
h)
uso
;;
f)
# OPTARG contém o argumento fornecido para -f
NOME_ARQUIVO="$OPTARG"
echo "Nome do arquivo de saída definido como: $NOME_ARQUIVO"
;;
\?)
# Lida com opções não reconhecidas
echo "Erro: Opção inválida -$OPTARG" >&2
uso
;;
:)
# Lida com argumentos ausentes para opções que requerem um (por exemplo, -f sem um nome de arquivo)
echo "Erro: A opção -$OPTARG requer um argumento." >&2
uso
;;
esac
done
# --- Deslocando Argumentos Posicionais ---
# Após getopts terminar, OPTIND contém o índice do primeiro argumento não opcional.
# Usamos shift para descartar todas as opções analisadas, deixando apenas argumentos posicionais ($1, $2, etc.).
shift $((OPTIND - 1))
# Verifica se o argumento posicional obrigatório (ENTRADA) está presente
DADOS_ENTRADA="$1"
if [ -z "$DADOS_ENTRADA" ]; then
echo "Erro: Dados de entrada obrigatórios."
uso
fi
echo "---"
echo "Processando entrada: $DADOS_ENTRADA"
echo "Status verboso: $VERBOSO"
Dica: Sempre use
shift $((OPTIND - 1))imediatamente após o loopwhile getoptspara separar claramente as opções dos argumentos posicionais restantes.
Lidando com Opções Longas como --option
O getopts embutido do Bash puro só suporta opções curtas. Para lidar com opções longas modernas (por exemplo, --verbose, --output-file=data.log), você deve implementar um loop de análise personalizado usando while e case com o comando shift.
Este método requer gerenciamento de argumentos mais explícito.
Analisador de Opções Longas Personalizado
#!/bin/bash
# --- Padrões ---
VERBOSO=0
ARQUIVO_SAIDA=""
# Função personalizada para exibir uso (omitida por brevidade)
# uso() { ... }
while [ "$#" -gt 0 ]; do
case "$1" in
--verbose)
VERBOSO=1
shift
;;
--output-file)
# Requer dois shifts: um para a flag, um para o valor
if [ -z "${2:-}" ]; then
echo "Erro: --output-file requer um valor."
exit 1
fi
ARQUIVO_SAIDA="$2"
shift 2
;;
--help)
uso
;;
-*)
echo "Erro: Opção desconhecida $1" >&2
exit 1
;;
*)
# Encontrou o primeiro argumento posicional, para de analisar opções
break
;;
esac
done
# Os argumentos restantes agora estão disponíveis como $1, $2, etc.
# ... A lógica do script continua ...
if [ "$ARQUIVO_SAIDA" ]; then
echo "Dados redirecionados para $ARQUIVO_SAIDA"
fi
Se seu script aceita argumentos posicionais após as opções, continue analisando até encontrar -- ou o primeiro argumento não opcional. Uma convenção comum é deixar -- significar "pare de analisar opções agora":
while [ "$#" -gt 0 ]; do
case "$1" in
--)
shift
break
;;
--verbose)
VERBOSO=1
shift
;;
*)
break
;;
esac
done
Avançado: Lidando com Opções Longas Chave-Valor (--key=value)
Se você prefere o estilo UNIX padrão onde os argumentos são passados usando um sinal de igual, você precisa usar substituição de parâmetros para dividir o argumento.
while [ "$#" -gt 0 ]; do
case "$1" in
--limit=*)
VALOR_LIMITE="${1#*=}" # Remove tudo até e incluindo '='
echo "Limite definido como: $VALOR_LIMITE"
shift
;;
# ... outras opções ...
esac
done
Melhores Práticas para Scripts Robusto
A. Combinando Opções Curtas e Longas
Para máxima flexibilidade, scripters experientes frequentemente combinam a confiabilidade do getopts para opções curtas com o loop while/case personalizado para opções longas. O loop de opções longas é executado primeiro, consumindo flags longas, e então os argumentos restantes (incluindo opções curtas) são processados pelo getopts.
No entanto, um padrão comum e mais limpo é processar todos os argumentos em um loop personalizado robusto que procura tanto -o quanto --option, deslocando conforme necessário.
B. Tratamento de Erros e Uso
Sempre forneça uma função uso clara que explique os argumentos e opções obrigatórios do script. Esta função deve ser chamada quando:
- O usuário solicita ajuda (por exemplo,
-hou--help). - Um argumento obrigatório está faltando.
- Uma opção inválida ou desconhecida é fornecida.
Certifique-se de que o script saia com um status diferente de zero em caso de erro (exit 1) e envie mensagens de erro para a Saída de Erro Padrão (>&2).
C. Valores Padrão
Inicialize todas as variáveis de configuração no início do script com valores padrão sensatos. Isso torna seu script previsível mesmo se nenhum argumento opcional for passado.
# Sempre inicialize variáveis antes de analisar
NIVEL_LOG="info"
FORCAR=0
Conclusão
Use argumentos posicionais para valores obrigatórios simples, getopts para opções curtas portáteis e um loop while/case personalizado quando precisar de opções longas. Teste valores ausentes, flags desconhecidas e argumentos com espaços antes de confiar no script em automação.