Postagem em destaque

Criando parâmetros em scripts

Provavelmente você já deve ter criado inúmeros scripts para a mais diversas finalidades; alguns são esquecidos enquanto outros se tornam importantes no uso diário. Um script que se preze, precisa estar bem escrito, contendo fartos comentários e que oferece opções claras de utilização; facilitando assim o uso de terceiros.

Porque não adicionar um recurso extra ao seu script ? Como permitir que parâmetros e argumentos sejam passados durante a execução. Já imaginou criar um documentação que possa ser acessada utilizando o parâmetro '-h' ?

$ script -h

Assim será retornado um texto contendo tudo o que usuário precisa saber sobre a execução e a descrição de cada parâmetro. O script ficará mais profissional, oferecendo parâmetros que determinaram o comportamento da sua execução.

Os comandos que irei abordar:

Comando Descrição
getopts Analisa parâmetros posicionais curtos.
getopt Analisa parâmetros posicionais longos e curtos.


getopts


O getopts é usando em procedimentos do shell para analise de parâmetros posicionais curtos como opções passadas no script.

Sintaxe:

getopts OPÇÕES NOME [ARG]

Variáveis utilizadas:

VariávelDescrição
OPTINDTotal de parâmetros (Inicializa com: 1)
OPTSTRINGContém as letras das opções a serem reconhecidas.
OPTARGContém a sequência de caracteres da opção.
OPTERRHabilita/Desabilita impressão da mensagem de erro.
0: desabilita e 1: habilitada (padrão)
As variáveis são inicializadas pelo getopts.

Exemplo


Criando o script xgetopts.sh com uma aplicação bem simples de uso do getopts.


#!/bin/bash

# Exemplo
# Script: xgetopts.sh

while getopts ab:cde OPCAO
do
    # Verifica o parâmetro armazenado em 'OPCAO'
    case $OPCAO in
        # Atribui uma ação.
        'a') opcao_A=1 ;;
        'b') argumento_B="$OPTARG" ;;
        'c') opcao_C=1 ;;
        'd') opcao_D=1 ;;
        'e') opcao_E=1 ;;
    esac
done

# Testa os valores das variáveis.
[ $opcao_A ] && echo "Opção 'A' foi ativada."
[ $argumento_B ] && echo "Opção 'B' foi ativada com o valor '$argumento_B'."
[ $opcao_C ] && echo "Opção 'C' foi ativada."
[ $opcao_D ] && echo "Opção 'D' foi ativada."
[ $opcao_E ] && echo "Opção 'E' foi ativada."

exit 0
#FIM

Entendendo


ExpressãoDescrição
ab:cdeUma sequência de caracteres que representam os parâmetros definidos por um caractere único. O caractere ':' (dois-pontos) após a letra, indica que o argumento é obrigatório.
OPCAOOnde o getopts irá armazenar o parâmetro atual.

  1. O getopts lê os parâmetros, armazenando o parâmetro da vez em OPCAO, o case avalia o valor armazenado executando o bloco de instrução respectivo atribuindo o valor de cada variavel opcao_* ou argumento_B.
  2. Os blocos condições (if), verifica se há valores nas variáveis indicando que o parâmetro foi chamado e imprime uma mensagem na tela.



Parâmetro '-a'


$ ./xgetopts.sh -a
Opção 'A' foi ativada.

Parâmetro '-c'

$ ./xgetopts.sh -C
Opção 'C' foi ativada.

Tentando executar o parâmetro '-b' sem argumentos.


./xgetopts.sh -b
./xgetopts.sh: opção requer um argumento -- b
A inserção do caractere ':' informa ao comando que o argumento é obrigatório.

Passando com argumento.

$ ./xgetopts.sh -b param
Opção 'B' foi ativada com o valor 'param'.
Além de informar que a opção foi ativada, imprimiu o argumento 'param' armazenado em OPTARG.

Com múltiplos parâmetros.


./xgetopts.sh -a -b param -d
Opção 'A' foi ativada.
Opção 'B' foi ativada com o valor 'param'.
Opção 'D' foi ativada.
Cada parâmetro utilizado foi tratado pelo comando.

Tratando erros


Por padrão o getopts imprime uma mensagem de erro na tela quando encontra um parâmetro inválido, enviando o caractere '?' (interrogação) para a variável do loop e limpa o valor de OPTARG.

Para criar uma mensagem de erro personalizada, precisamos habilitar o modo silencioso do getopts, atribuindo o valor '0' (zero) à variável OPTERR e tratar a opção '?' no case.

Veja o código a seguir:


#!/bin/bash

# Exemplo
# Script: xgetopts.sh

# *** HABILITANDO MODO SILENCIOSO ***
OPTERR=0

while getopts ab:cde OPCAO
do
    # Verifica o parâmetro armazenado em 'OPCAO'
    case $OPCAO in
        # Atribui uma ação.
        'a') opcao_A=1 ;;
        'b') argumento_B="$OPTARG" ;;
        'c') opcao_C=1 ;;
        'd') opcao_D=1 ;;
        'e') opcao_E=1 ;;
        # *** TRATANDO O ERRO AQUI ***
        '?') echo 'Ocorreu um erro !!'; exit 1;;
    esac
done

# Testa os valores das variáveis.
[ $opcao_A ] && echo "Opção 'A' foi ativada."
[ $argumento_B ] && echo "Opção 'B' foi ativada com o valor '$argumento_B'."
[ $opcao_C ] && echo "Opção 'C' foi ativada."
[ $opcao_D ] && echo "Opção 'D' foi ativada."
[ $opcao_E ] && echo "Opção 'E' foi ativada."

exit 0
#FIM


Executando o script com o parâmetro '-b' sem argumentos.

$ ./xgetopts.sh -b
Ocorreu um erro !!
Nossa mensagem personalizada foi retornada e o script finalizado com status 1.

O razão de habilitar o modo silencioso é evitar que duas mensagens de erro sejam retornadas, tanto a personalizada como a diagnostico nativa do getopts.

Opção ajuda


A opção de ajuda tradicionalmente conhecida pelo parâmetro curto '-h', tem como função retornar informações relevantes a utilização do comando/script. Através dela teremos conhecimento da sua sintaxe, descrição, parâmetros, exemplos e etc. De nada adianta um script cabuloso capaz de fazer milagres se não possui uma documentação que nos mostre o caminho.

Para criar o recurso de ajuda, precisaremos inserir um novo parâmetro ao script. Para isso devemos incluir o caractere 'h' na expressão do getopts junto aos demais caracteres, depois criar sua entrada na estrutura do case e no final montar o layout da ajuda a ser retornada ao usuário.

Observe o código a seguir:


#!/bin/bash

# Exemplo
# Script: xgetopts.sh

# Habilita modo silencioso do getopts
OPTERR=0

while getopts ab:cdeh OPCAO
do
    # Verifica o parâmetro armazenado em 'OPCAO'
    case $OPCAO in
        # Atribui uma ação.
        'a') opcao_A=1 ;;
        'b') argumento_B="$OPTARG" ;;
        'c') opcao_C=1 ;;
        'd') opcao_D=1 ;;
        'e') opcao_E=1 ;;
        # Tratando erro aqui.
        '?') echo 'Ocorreu um erro !!'; exit 1;;
        'h') # *** AJUDA ***
             # xgetopts.sh -h
            echo "Uso: $0 [OPÇÕES]..."
            echo 'Script de teste que demonstra o uso de parâmetros.'
            echo
            echo 'Aceita somente parâmetros curtos.'
            echo '-a    Ativa opção A.'
            echo '-b    Ativa opção B. (Argumento obrigatório)'
            echo '-c    Ativa opção C.'
            echo '-d    Ativa opção D.'
            echo '-e    Ativa opção E.'
            echo '-h    Exibe ajuda.'
            echo
            echo 'Estado de saida:'
            echo '0  se estiver tudo OK'
            echo '1  caso apresente problemas. (por exemplo: argumento inválido.)'
            echo
            echo 'Criado por: <Juliano Santos> [SHAMAN]'

            # Estado de saida 0
            exit 0
            ;;
    esac
done

# Testa os valores das variáveis.
[ $opcao_A ] && echo "Opção 'A' foi ativada."
[ $argumento_B ] && echo "Opção 'B' foi ativada com o valor '$argumento_B'."
[ $opcao_C ] && echo "Opção 'C' foi ativada."
[ $opcao_D ] && echo "Opção 'D' foi ativada."
[ $opcao_E ] && echo "Opção 'E' foi ativada."

exit 0
#FIM
Note que ao final do layout, inserimos o 'exit 0' para finalizar o script. Uma vez que a opção de ajuda é solicitada, não há motivos para continuar verificando os demais parâmetros.

Exibindo ajuda do comando.


$ ./xgetopts.sh -h
Uso: ./xgetopts.sh [OPÇÕES]...
Script de teste que demonstra o uso de parâmetros.

Aceita somente parâmetros curtos.
-a    Ativa opção A.
-b    Ativa opção B. (Argumento obrigatório)
-c    Ativa opção C.
-d    Ativa opção D.
-e    Ativa opção E.
-h    Exibe ajuda.

Estado de saida:
0  se estiver tudo OK
1  caso apresente problemas. (por exemplo: argumento inválido.)

Criado por: <Juliano Santos> [SHAMAN]

Agora nosso script possui um recurso de ajuda, onde está descrito seus parâmetros e que podem ser acessados facilmente através da linha de comando:

$ ./xgetopts -h

Observações


  • O getopts analisa os parâmetros posicionais ($0 - $9), porém se mais argumentos forem dados, eles serão analisados.
  • Apesar dos parâmetros serem caracteres únicos, tenha a boa prática de usar aspas simples ou duplas na estrutura case; para evitar que caracteres especiais seja interpretados como parte de uma expressão regular.  Exemplo: O '?' que utilizamos no tratamento de erros se estiver fora das aspas, será considerado como um metacaractere  que indica opcional. Exceto se utilizar antes um caractere de escape. Exemplo: \?.

getopt


O getopt é usado para dividir opções em linhas de comando a serem analisadas. Apesar de ter o nome parecido, mas no singular; ele possui recursos distintos. Suporta parâmetros longos e curtos, chamada externa para reportar erros, definir convenção entre outros.

Sintaxe:

getopt [options] -o|--options <optstring> [options] [--] <parameters>

Opções utilizadas:

OpçãoDescrição
--longoptionsOpções longas a serem reconhecidas.
--optionsOpções curtas a serem reconhecidas.
--nameNome sob o qual os erros serão reportados.

Criei um script chamando xgetopt.sh para demonstrar seu uso:


#!/bin/bash

# Script: xgetopt.sh

# Montei as opções do getopt, com os parâmetros curtos e longos.
OPTS=$(getopt --options 'dpc:' --longoptions 'detalhes,porta,conectar:' --name "$(basename $0)" -- "$@")

# Convertendo 'optstring' em parâmetros posicionais ($0 - $9)
eval set -- "$OPTS"

# Executa loop infinito
while true
do
    case $1 in
        -d|--detalhes)
            opcao_1=1
            param_1=$1  # Armazena parâmetro 1
            shift 1     # Desloca um nível
            ;;
        -p|--porta)
            opcao_2=1
            param_2=$1  # Armazena parâmetro 2
            shift 1     # Desloca um nível.
            ;;
        -c|--conectar)
            opcao_3=1
            param_3=$1  # Armazena parâmetro 3
            arg="$2"    # Armazena argumento
            shift 2     # Desloca dois níveis.
            ;;
        --)
            # Se não houver mais parâmetros.
            # Desloca um nível e interrompe o loop.
            shift
            break
            ;;
    esac
done

# Verica se há valores nas variáveis.
[ $opcao_1 ] && echo "Parâmetro '$param_1' ativado."
[ $opcao_2 ] && echo "Parâmetro '$param_2' ativado."
[ $opcao_3 ] && echo "Parâmetro '$param_3' ativado com argumento '$arg'."

exit 0
#FIM
Note a utilização do caractere ':' (dois pontos) para argumentos obrigatórios, presente no parâmetro curto e longo do comando getopt.

Executando script com parâmetro longo '--detalhes'.

$ ./xgetopt.sh --detalhes
Parâmetro '--detalhes' ativado.

Executando com parâmetro longo com argumento.

$ ./xgetopt.sh --conectar servidor
Parâmetro '--conectar' ativado com argumento 'servidor'.

Múltiplos parâmetros

$ ./xgetopt.sh --conectar servidor --detalhes --porta
Parâmetro '--detalhes' ativado.
Parâmetro '--porta' ativado.
Parâmetro '--conectar' ativado com argumento 'servidor'.


Entendendo


O getopt trata a leitura das opções de uma forma diferente, alocando em uma variável toda a expressão contendo os parâmetros e argumentos. A implementação do getopt é incapaz de lidar com espaços em branco e outros caracteres especiais em argumentos ou parâmetros. Para resolver esse problema devemos usar o comando eval para conversão da expressão em parâmetros posicionais. O uso do '--' (hifén), atribui quaisquer argumentos restantes ao parâmetro de posição, caso contrário o parâmetro é indefinido.

Parâmetros curtos e longos geralmente são expressados seguindo a mesma ordem posicional dentro da estrutura do comando, onde parâmetros longos são separados por uma ',' (vírgula).


O deslocamento dos parâmetros posicionais é feita através do comando shift n, onde 'n' determina o número de deslocamentos. 


Considere a seguinte linha de comando:

$ ./xgetopt.sh --porta --conectar servidor --detalhes

Etapas:
  1. O getopt , trata todos os elementos em '$@' e armazena em OPTS.
  2. O comando eval set -- "$OPTS" atribui os argumentos que faltam ao parâmetro da posição, convertendo os elementos em parâmetros posicionais ($0 - $9). 
  3. Inicia um loop infinito
  4. O case lê o elemento da vez em '$1'. Se for um parâmetro válido, executa as instruções referentes e desloca o nível dos elementos.
  5. Se o elemento for um parâmetro indefinido '--', desloca um nível e interrompe o loop.

Parâmetros posicionais:

 Observações

  •  O getopt não desloca automaticamente os elementos, sendo necessário a utilização do comando shift.
  • Em caso de parâmetros inválidos ou indefinidos, devemos tratar a opção '--' na estrutura do case.
  • Ao final dos elementos o parâmetro indefinido '--' é retornado.

Feito !! Essa foi uma prévia de como criar um script "profissa" com suporte a passagem de parâmetros. Agora; se for empregar um único parâmetro, não há necessidade de todo esse trabalho. Um simples 'if' já resolve o seu problema.

Comentários

Contato

Nome

E-mail *

Mensagem *