Como faço para lidar com opções em um script de shell?

Existem ferramentas integradas que reconhecerão -x e --xxxx como opções, e não como argumentos, ou você tem que passar por todas as variáveis de entrada, testar traços e, em seguida, analisar os argumentos?

Resposta

Use getopts .

É justo portátil, pois é na especificação POSIX. Infelizmente, ele não suporta opções longas.

Veja também este getopts tutorial cortesia de o wiki bash-hackers e esta pergunta do stackoverflow.

Se você só precisa de opções curtas, padrão de uso típico para getopts (usando relatório de erro não silencioso) é:

# process arguments "$1", "$2", ... (i.e. "$@") while getopts "ab:" opt; do case $opt in a) aflag=true ;; # Handle -a b) barg=$OPTARG ;; # Handle -b argument \?) ;; # Handle error: unknown option or missing required argument. esac done 

Comentários

  • Deve ser mencionado que getopt deve sempre ser verificado como GNU getopt antes de usá-lo, mas você não deve ' usá-lo de qualquer maneira como getopts é mais portátil (e geralmente mais agradável) de qualquer maneira. Se você precisa de chamá-lo por algum motivo, chame de uma maneira específica do GNU, e certifique-se de que GETOPT_COMPATIBLE não está no ambiente.
  • O que os dois pontos em while getopts "ab:" opt fazem?
  • @ user394 O : após uma letra de opção significa isso requer um argumento. Um : como o primeiro caractere significa suprimir mensagens de erro.

Resposta

Presumo que você esteja usando bash ou similar. Um exemplo:

all=false long=false while getopts ":hal" option; do case $option in h) echo "usage: $0 [-h] [-a] [-l] file ..."; exit ;; a) all=true ;; l) long=true ;; ?) echo "error: option -$OPTARG is not implemented"; exit ;; esac done # remove the options from the positional parameters shift $(( OPTIND - 1 )) ls_opts=() $all && ls_opts+=( -a ) $long && ls_opts+=( -l ) # now, do it ls "${ls_opts[@]}" "$@" 

Comentários

  • +1 para usar += com uma matriz. Não ' não sabia que você poderia fazer isso. Legal!

Resposta

Você deve escrever um ciclo para analisar os parâmetros. Na verdade, você pode usar getopts comando para fazer isso facilmente.

Este é um exemplo simples da getopts página do manual:

aflag= bflag= while getopts ab: name do case $name in a) aflag=1;; b) bflag=1 bval="$OPTARG";; ?) printf "Usage: %s: [-a] [-b value] args\n" $0 exit 2;; esac done if [ ! -z "$aflag" ]; then printf "Option -a specified\n" fi if [ ! -z "$bflag" ]; then printf "Option -b "%s" specified\n" "$bval" fi shift $(($OPTIND - 1)) printf "Remaining arguments are: %s\n" "$*" 

Resposta

Escrevi recentemente um script para o trabalho que era versátil e permitia vários tipos de interruptores em qualquer ordem. Não consigo divulgue o roteiro completo por razões legais óbvias (sem mencionar que não o tenho comigo no momento), mas aqui está o ponto principal … você pode colocá-lo i em uma sub-rotina e chame-a no final de seu script:

options () { if [ -n "$1" ]; then # test if any arguments passed - $1 will always exist while (( "$#" )); do # process ALL arguments if [ "$1" = ^-t$ ]; then # -t short for "test" # do something here THEN shift the argument # shift removes it from $@ and reduces $# by # one if you supply no argument shift # we can also process multiple arguments at once elif [[ "$1" =~ ^--test=[:alnum:]{1,8}$ ]] && [[ "$2" =~ ^-t2$ ]] && [[ -n "$3" ]]; then # check for 3 arguments # do something more then remove them ALL from the arg list shift 3 else echo "No matching arguments!" echo "Usage: [script options list here]" fi done else echo "Usage: [script options list here]" exit 0 fi } options "$@" # run options and loop through/process ALL arguments 

Eu recomendo limitar seu script bash a menos de 400 linhas / 15k caracteres; meu script mencionado cresceu além desse tamanho e tornou-se muito difícil de trabalhar. Comecei a reescrevê-lo em Perl, que é muito mais adequado para a tarefa. Tenha isso em mente ao trabalhar em seus scripts no bash. Bash é ótimo para pequenos scripts e oneliners, mas qualquer coisa mais complexa e é melhor escrever em Perl.

Observe, eu não testei o acima, então provavelmente não funciona, mas você obtém uma ideia geral disso.

Comentários

  • A maneira como você chama options no final não está correto, ele retornará -bash: syntax error near unexpected token $@. Chame-o de options "$@".
  • Sim, eu confundi Perl e Bash. Corrigido.
  • Essa while condição não deve ser (($#)) em vez disso?
  • Por que você precisaria de dois conjuntos de parênteses para $#? Editar: você ' está certo. Corrigido para while (( "$#" ))

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *