Lidando com argumento getopts não utilizados (as opções não são obrigatórias?)

1

Eu tenho um script que começa com getopts e se parece com o seguinte:

USAGE() { echo -e "Usage: bash $0 [-w <in-dir>] [-o <out-dir>] [-c <template1>] [-t <template2>] \n" 1>&2; exit 1; }

if (($# == 0))
then
    USAGE
fi

while getopts ":w:o:c:t:h" opt
do
    case $opt in
        w ) BIGWIGS=$OPTARG
        ;;
        o ) OUTDIR=$OPTARG
        ;;
        c ) CONTAINER=$OPTARG
        ;;
        t ) TRACK=$OPTARG
        ;;
        h ) USAGE
        ;;
        \? ) echo "Invalid option: -$OPTARG exiting" >&2
       exit
        ;;
        : ) echo "Option -$OPTARG requires an argument" >&2
        exit
        ;;
    esac
done

more commands etc

echo $OUTDIR
echo $CONTAINER

Eu estava fazendo alguns testes neste script e em algum momento, eu não precisei / quis usar o argumento -c [-c]. Em outras palavras, eu estava tentando testar outra parte específica do script que não envolvia a variável $ CONTAINER. Portanto, eu simplesmente adicionei # na frente de todos os comandos com o $ CONTAINER e fiz alguns testes que foram bons.

Ao testar o script sem usar $ CONTAINER, digitei:

bash script.bash -w mydir -o myoutdir -t mywantedtemplate

No entanto, eu estava pensando, dado o meu comando getopts eu não recebi um aviso. Em outras palavras, por que eu não recebi um aviso pedindo o argumento -c. Isso é possível? O aviso só ocorre se eu digitar:

bash script.bash -w mydir -o myoutdir -t mywantedtemplate -c

UPDATE

Depois de fazer alguns testes, acho que é isso:

  • Se você não escrever explicitamente "-c", getopts não lhe "pedirá" e lhe dará um erro (a menos que seu script esteja fazendo alguma coisa com ele - por exemplo, se você não colocou # na frente de cada comando usando este argumento)
  • Você só recebe um erro se colocar "-c" e nada mais

Isso está correto? Presumivelmente, o que eu fiz foi "má prática" e deve ser evitado: ao testar, devo remover o c: do comando getopts completamente.

Eu acho que o que estou perguntando é: quando você diz getopts sobre os argumentos (a linha "while" no meu script), estamos dizendo: estas são as opções que você pode esperar e as seguidas por um ":" devem ter argumento com eles. Mas eles não têm que ser dado. Ou seja você pode esperar uma opção c com um argumento mas não lançar um erro se você não tiver a opção c.

    
por m93 14.09.2018 / 11:12

2 respostas

1

O utilitário getopts não sabe sobre as opções obrigatórias , apenas sobre quais opções são permitidas (e quais opções delas devem ter um argumento de opção). Se você quiser impor opções obrigatórias, você teria que fazer isso com seus próprios testes em ou após o loop de análise de opções.

O utilitário getopts não faz isso porque as opções podem ter relacionamentos mais complexos, como algumas opções conflitantes, algumas opções que exigem a presença de outras opções etc. Isso é deixado para o autor do script resolver com sua própria lógica .

    
por 14.09.2018 / 11:31
1

Eu não sei exatamente o que você está perguntando, mas o que o getopts faz é que ele analisa a linha de comando que já foi dada ao programa e mostra as opções que ele vê. por um, em um formato que é um pouco fácil para o código do programa manipular. Tem a opção de imprimir erros para opções que não conhece, mas é tudo o que faz.

Realmente não "pede" nada de ninguém, já que a linha de comando já está corrigida quando getopts é chamado. Não há interação, a menos que o restante do programa implemente isso.

Também não, e não pode saber quais opções são necessárias para o programa funcionar (não há sintaxe para isso no "optstring" getopts como argumento). O caso comum é que as opções no são necessárias (pense em ls , rm , vi ...) e, nos casos em que você tenha solicitado opções, você pode verificar manualmente no script.

Considere este exemplo:

#!/bin/bash

opt_a=
opt_b=
while getopts 'a:bc' opt; do
    case $opt in
        a) opt_a=$OPTARG;;
        b) opt_b=1;;
    esac
done

if [ -z "$opt_a" ]; then
    echo "option a was NOT given, exit."
    exit 1;
fi
echo "do something with a='$opt_a' b=$opt_b"

O script verifica explicitamente se a foi dado. Sem o cheque, o programa ficaria feliz sem ele. getopts também é avisado para aceitar c como uma opção e não fornece um erro. O script simplesmente o ignora completamente, pois eu não coloquei um caso c) ou *) lá. Não há como getopts saber que essa opção específica será ignorada.

Observe que o significado habitual de colchetes em uma dica de uso é informar que uma opção é opcional, portanto, se você quiser dizer que todos os -w , -o , -c , -t devem ser fornecidos para sua script, sugiro soltar os colchetes.

    
por 14.09.2018 / 11:53