Como posso detectar que nenhuma opção foi passada com getopts?

15

Eu tenho este código -

#getoptDemo.sh
usage()
{
    echo "usage: <command> options:<w|l|h>"
}
while getopts wlh: option
do
    case $option in
            (w)
                    name='1';;
            (l)
                    name='2';;
            (h)
                    name='3';;
            (*)
                    usage
                    exit;;
    esac
done
print 'hi'$name

Quando executo bash getoptDemos.sh (sem a opção), ele imprime hi em vez de chamar a função usage . Ele chama o uso quando outras opções além de w, he são dadas. Então não funciona quando nenhuma opção é especificada.

Eu tentei usar ? , \? , : no lugar de * , mas não consegui o que queria. Quero dizer, todo o docs on getopt diz para usar ? .

O que estou fazendo de errado?

    
por Hussain Tamboli 11.10.2012 / 10:47

4 respostas

13

Quando você executar este script sem nenhuma opção, o getopt retornará false, para que ele não entre no loop. Ele só vai descer para a impressão - é este ksh / zsh?

Se você tiver uma opção, é melhor testar $ name após o loop.

if [ -z "$name" ]
then
   usage
   exit
fi

Mas certifique-se de que $name estava vazio antes de chamar getopts (como poderia ter havido um $name no ambiente que o shell recebeu na inicialização) com

unset name

(antes do loop getopts )

    
por 11.10.2012 / 10:57
19

getopts processa as opções por sua vez. Esse é o seu trabalho. Se o usuário não passar nenhuma opção, a primeira chamada de getopts sairá do loop while.

Se nenhuma das opções receber um argumento, o valor de OPTIND indica quantas opções foram passadas. Em geral, OPTIND é o número de argumentos que são opções ou argumentos para opções, em oposição a argumentos não opcionais (operandos).

while getopts …; do …; done
if [ $OPTIND -eq 1 ]; then echo "No options were passed"; fi
shift $((OPTIND-1))
echo "$# non-option arguments"

Em qualquer caso, você não está tentando determinar se não havia opções, mas se nenhuma das opções name -setting foi passada. Portanto, verifique se name não está definido (e tenha o cuidado de desativá-lo primeiro) .

    
por 12.10.2012 / 01:34
2

Se o seu script deve receber argumentos de opção em qualquer caso, coloque este bloco no começo (antes dos getops).

if [[ ! $@ =~ ^\-.+ ]]
then
  #display_help;
fi

Block verifica se a string de parâmetro não começa com o símbolo - , o que indica que o primeiro parâmetro não é um argumento de opção.

    
por 31.05.2016 / 18:52
0

Pouco antes do bloco getopts , verifique se $1 (o primeiro argumento / opção que você passou na linha de comando) é igual a uma string vazia. Se estiver, imprima a mensagem de uso e saia (ou execute alguma função "sem opções" se você for um anarquista), caso contrário, deixe getopts analisar as opções como normal.

A razão pela qual este recurso não está incluído no getopts, é porque você já pode realizá-lo no bash com um "if-else". Exemplo:

if [[ $1 == "" ]]; then
    Your_Usage_Function;
    exit;
else
   #parse options with getopts code block here;
fi

Faz sentido?

    
por 31.10.2016 / 17:59