GETOPTS analisa argumentos vazios e não vazios

0

Estou tentando criar um script que tenha duas opções -h e -d, -d com um argumento de número obrigatório. Depois disso, haverá um número indeterminado de caminhos para o arquivo. Até agora, eu tenho isso, mas o código parece não reconhecer inválido switch -r (pode ser qualquer nome) e também não funciona quando eu não introduzir quaisquer opções:

while getopts ":hd:" opt; do
case $opt in
    h)
            echo $usage
        exit 0
            ;;
    d)
        shift 2
            if [ "$OPTARG" -eq "$OPTARG" ] ; then # ako dalsi argument mame cislo
            depth=$OPTARG
        fi
            ;;
        \?)
        shift 1
            ;;
        :)
            shift 1
            ;;
esac
done
echo $1

quando digito ./pripravne1.sh -d /home/OS/test_pz/test2 recebo ./pripravne1.sh: [: /home/OS/test_pz/test2: integer expression expected quando digito ./pripravne1.sh -r /home/OS/test_pz/test2 , recebo apenas uma string vazia.

    
por Traabefi 22.10.2018 / 21:40

2 respostas

5

[ "$OPTARG" -eq "$OPTARG" ] ... não é o caminho certo para verificar se $OPTARG é numérico - pode imprimir um erro desagradável desagradável ao usuário, se não for o caso, ou pode simplesmente retornar true em todos os casos (em ksh ), ou também retorna true para um $OPTARG vazio (em zsh ).

Além disso, uma opção que aceita um argumento pode ser dada como -d12 ou -d 12 , portanto, um cego shift 2 não o cortará. E fazer um shift dentro do loop pode incorretamente interratar com getopts , que está usando a lista de argumentos ativos.

Levando isso em conta, é isso que proponho:

die(){ echo >&2 "$@"; exit 1; }
usage(){ echo >&2 "usage: $0 [-h] [-d num] files..."; exit 0; }

depth=0

while getopts :hd: opt; do
        case $opt in
        h)      usage ;;
        d)      case $OPTARG in
                ''|*[!-0-9]*|-|*?-*) die "invalid number $OPTARG" ;;
                *) depth=$OPTARG ;;
                esac
                ;;
        :)      die "argument needed to -$OPTARG" ;;
        *)      die "invalid switch -$OPTARG" ;;
        esac
done
shift "$((OPTIND - 1))"

echo depth="$depth"
echo files="$@"
    
por 22.10.2018 / 22:39
0

O colchete simples [ é compatível com posix, mas é mais difícil de usar do que [[ , que você geralmente pode usar no bash. Sob o padrão de colchetes únicos, -eq é apenas para números inteiros, não para cadeias. Por exemplo, o seguinte funciona bem: if [ "2" -eq "2" ] ; then echo foo; fi . Você pode usar colchetes duplos, para os quais -eq aceita cadeias ou use = e o formato de colchete único:

if [ "bar" = "bar" ] ; then echo foo; fi

Confira o link para informações sobre o POSIX se teste e link para obter informações sobre diferentes tipos de construções de teste, como (( e [[ .

    
por 22.10.2018 / 21:58