Processamento de Opções em Scripts Shell Linux

Ao invocar parâmetros de linha de comando via parâmetros posicionais, a ordem de entrada dos argumentos deve ser fixa, o que pode levar a erros se a sequência for incorreta. Para tornar scripts mais robustos e evitar esse problema, especialmente em funcionalidades complexas, é comum implementar suporte a opções, semelhante a ferramentas de linha de comando do Linux, onde diferentes opções e argumentos podem ser especificados.

Uso de Instrução case para Opções de Linha de Comando

Quando um script Shell precisa lidar com apenas uma opção de linha de comando, a instrução case pode ser utilizada.

$ cat gerencia_arquivo.sh
#!/bin/bash
# Script para processar arquivos com opções básicas

opcao=$1
nome_arquivo=$2

verifica_arquivo() {
    if [ -z "$nome_arquivo" ]; then
        echo "Nome do arquivo ausente"
        exit 1
    elif [ ! -f "$nome_arquivo" ]; then
        echo "O arquivo $nome_arquivo não existe"
        exit 2
    fi
}

case "$opcao" in
    -e|-E)
        verifica_arquivo
        echo "Editando o arquivo $nome_arquivo..."
        ;;
    -p|-P)
        verifica_arquivo
        echo "Exibindo o arquivo $nome_arquivo..."
        ;;
    *)
        echo "Argumento inválido!"
        echo "Uso: $(basename "$0") -e|-p nome_arquivo"
        exit 3
        ;;
esac

Exemplo de execução:

$ ./gerencia_arquivo.sh
Argumento inválido!
Uso: gerencia_arquivo.sh -e|-p nome_arquivo

$ ./gerencia_arquivo.sh -p
Nome do arquivo ausente

$ ./gerencia_arquivo.sh -p lista.txt
Exibindo o arquivo lista.txt...

$ ./gerencia_arquivo.sh -E lista.txt
Editando o arquivo lista.txt...

Uso de getopts para Múltiplas Opções

O comando interno getopts do Bash permite analisar opções e argumentos de forma profissional. Ele oferece vantagens como não depender de programas externos, facilidade para definir variáveis Shell e conformidade com POSIX. No entanto, getopts não suporta opções longas no estilo GNU (ex.: --minha-opção) ou XF86 (ex.: -minha-opção).

Características principais:

  • Reconhece opções como letras maiúsculas, minúsculas ou dígitos.
  • Deve ser chamado múltiplas vezes, geralmente em um loop while, pois não altera parâmetros posicionais automaticamente.
  • Interrompe a análise ao encontrar o primeiro argumento não-opção ou o delimitador duplo --.

Variáveis usadas por getopts:

  • OPTIND: Índice do próximo parâmetro a ser processado; reinicie para 1 antes de reutilizar.
  • OPTARG: Argumento associado à opção encontrada.
  • OPTERR: Controla a exibição de mensagens de erro (0 para suprimir, 1 para mostrar).

Sintaxe básica: getopts CADEIA_OPÇÕES VARIAVEL [ARGUMENTOS...], onde CADEIA_OPÇÕES define opções válidas (com : após letras para endicar argumentos obrigatórios), VARIAVEL armazena a opção atual, e ARGUMENTOS são parâmetros alternativos a serem analisados.

getopts suporta dois modos de relatório de erros: detalhado (com mensagens padrão) e suprimido (recomendado para scripts de produção).

Exemplo: Script com Opção Única

$ cat opcao_simples.sh
#!/bin/bash
# Demonstração básica de getopts

while getopts ":a" parametro; do
    case "$parametro" in
        a)
            echo "A opção -a foi ativada!"
            ;;
        \?)
            echo "Opção inválida: -${OPTARG}"
            ;;
    esac
done

Testes:

$ ./opcao_simples.sh
$ ./opcao_simples.sh texto.txt
$ ./opcao_simples.sh -b
Opção inválida: -b
$ ./opcao_simples.sh -a
A opção -a foi ativada!
$ ./opcao_simples.sh -a -b -c
A opção -a foi ativada!
Opção inválida: -b
Opção inválida: -c

Observações: Opções inválidas não interrompem o processamento; opções repetidas são permitidas, a menos que implemente verificação adicional.

Exemplo: Script com Múltiplas Opções

$ cat multiplo_opcoes.sh
#!/bin/bash
# Script com opções -h, -v, -f, -o

flag_verbose=off
arquivo_entrada=""
arquivo_saida=""

uso() {
    echo "USO: $(basename "$0") [-h] [-v] [-f <arquivo>] [-o <arquivo>]"
    exit 1
}

while getopts :hvf:o: opt; do
    case "$opt" in
        v) flag_verbose=on ;;
        f)
            arquivo_entrada="$OPTARG"
            if [ ! -f "$arquivo_entrada" ]; then
                echo "O arquivo de origem $arquivo_entrada não existe!"
                exit 2
            fi
            ;;
        o)
            arquivo_saida="$OPTARG"
            if [ ! -d "$(dirname "$arquivo_saida")" ]; then
                echo "O diretório de saída $(dirname "$arquivo_saida") não existe!"
                exit 3
            fi
            ;;
        h) uso ;;
        :)
            echo "A opção -$OPTARG requer um argumento."
            exit 4
            ;;
        ?)
            echo "Opção inválida: -$OPTARG"
            uso
            exit 5
            ;;
    esac
done

# Lógica adicional do script iria aqui
</arquivo></arquivo>

Execuções de exemplo:

$ ./multiplo_opcoes.sh -h
USO: multiplo_opcoes.sh [-h] [-v] [-f <arquivo>] [-o <arquivo>]

$ ./multiplo_opcoes.sh -vf
A opção -f requer um argumento.

$ ./multiplo_opcoes.sh -vf arquivo_inexistente.txt
O arquivo de origem arquivo_inexistente.txt não existe!

$ ./multiplo_opcoes.sh -vf arquivo.txt -o saida
</arquivo></arquivo>

Uso de getopt para Opções Longas e Flexibilidade

O comando getopt, disponível em sistemas Linux, é semelhante ao getopts, mas suporta opções longas (ex.: --opcao-longa) e oferece mais controle. Ele é um utilitário externo e requer tratamento diferente em scripts.

Sintaxe: getopt [opções] [--] cadeia-opções parâmetros, onde cadeia-opções segue o formato do getopts, e parâmetros são os argumentos a serem analisados.

Exemplo de uso básico:

$ getopt f:vl -vl -f/diretorio/arquivo param1
 -v -l -f /diretorio/arquivo -- param1

getopt reorganiza os parâmetros, adicionando o delimitador -- entre opções e argumentos posicionais.

Exemplo: Reescrevendo com getopt

$ cat processa_opcoes.sh
#!/bin/bash
# Script usando getopt para analisar opções

flag_verbose=off
arquivo_entrada=""
arquivo_saida=""

uso() {
    echo "USO: $(basename "$0") [-h] [-v] [-f <arquivo>] [-o <arquivo>]"
    exit 1
}

# Reconfigura parâmetros posicionais com getopt
set -- $(getopt hvf:o: "$@")

while [ $# -gt 0 ]; do
    case "$1" in
        -v) flag_verbose=on ;;
        -f)
            arquivo_entrada="$2"
            if [ ! -f "$arquivo_entrada" ]; then
                echo "O arquivo de origem $arquivo_entrada não existe!"
                exit 2
            fi
            shift ;;
        -o)
            arquivo_saida="$2"
            if [ ! -d "$(dirname "$arquivo_saida")" ]; then
                echo "O diretório de saída $(dirname "$arquivo_saida") não existe!"
                exit 3
            fi
            shift ;;
        -h) uso ;;
        --) shift; break ;;
        -*) echo "Opção inválida: $1"; uso; exit 4 ;;
        *) break ;;
    esac
    shift
done

# Restante do script...
</arquivo></arquivo>

Testes:

$ ./processa_opcoes.sh -h
USO: processa_opcoes.sh [-h] [-v] [-f <arquivo>] [-o <arquivo>]

$ ./processa_opcoes.sh -vf arquivo.txt -o saida
</arquivo></arquivo>

Exemplo: Suporte a Opções Longas

$ cat opcoes_longas.sh
#!/bin/bash
# Script com opções curtas e longas

valor_a=""
flag_b=0
valor_c=""

# Analisa opções curtas e longas com getopt
eval set -- $(getopt -o a::bc: --long opcao-a::,opcao-b,opcao-c: -n "$(basename "$0")" -- "$@")

while true; do
    case "$1" in
        -a|--opcao-a)
            case "$2" in
                "") valor_a="valor padrão"; shift ;;
                *) valor_a="$2"; shift ;;
            esac ;;
        -b|--opcao-b) flag_b=1 ;;
        -c|--opcao-c)
            case "$2" in
                "") shift ;;
                *) valor_c="$2"; shift; break ;;
            esac ;;
        --) shift; break ;;
        *) echo "Erro interno!"; exit 1 ;;
    esac
    shift
done

echo "VALOR_A= $valor_a"
echo "FLAG_B= $flag_b"
echo "VALOR_C= $valor_c"

Exemplos de execução com opções curtas:

$ ./opcoes_longas.sh
VALOR_A=
FLAG_B= 0
VALOR_C=

$ ./opcoes_longas.sh -a -b -c 789
VALOR_A= valor padrão
FLAG_B= 1
VALOR_C= 789

$ ./opcoes_longas.sh -a123 -b -c 789
VALOR_A= 123
FLAG_B= 1
VALOR_C= 789

Exemplos com opções longas:

$ ./opcoes_longas.sh --opcao-a --opcao-b --opcao-c 789
VALOR_A= valor padrão
FLAG_B= 1
VALOR_C= 789

$ ./opcoes_longas.sh --opcao-a=123 --opcao-b --opcao-c 789
VALOR_A= 123
FLAG_B= 1
VALOR_C= 789

$ ./opcoes_longas.sh --opcao-a 456
VALOR_A= valor padrão
FLAG_B= 0
VALOR_C=

Considerações sobre opções longas: para argumentos opcionais, use = para conectar (ex.: --opcao-a=valor); para argumentos obrigatórios, pode usar espaço ou =.

Escolha entre getopts e getopt com base nas necessidades: getopts para simplicidade e compatibilidade POSIX; getopt para suporte a opções longas e maior flexibilidade em ambientes Linux.

Tags: Bash Shell Scripting Command-line Parsing getopts getopt

Publicado em 6-8 05:11 por Thomas