Respostas:
Use getopts
.
É bastante portátil, como na especificação POSIX. Infelizmente, ele não suporta opções longas.
Veja também este getopts
tutorial, cortesia do wiki do bash-hackers e esta pergunta do stackoverflow.
Se você precisar apenas de opções curtas, o padrão de uso típico para getopts
(usando relatórios de erro não silenciosos) é:
# 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
while getopts "ab:" opt
faz?
:
letra de opção após indica que requer um argumento. A :
como o primeiro caractere significa suprimir as mensagens de erro.
Presumo que você esteja usando o 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[@]}" "$@"
+=
com uma matriz. Não sabia que você poderia fazer isso. Agradável!
Você precisa escrever um ciclo para analisar os parâmetros. Na verdade, você pode usar o getopts
comando para fazê-lo facilmente.
Este é um exemplo simples da getopts
página de 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" "$*"
Escrevi recentemente um script para um trabalho versátil e que permitia vários tipos de comutadores em qualquer ordem. Não posso divulgar o script 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 em uma sub-rotina e chamá-lo no final do 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 roteiro mencionado cresceu além desse tamanho e ficou muito difícil de trabalhar. Comecei a reescrevê-lo no Perl, que é muito mais adequado para a tarefa. Tenha isso em mente ao trabalhar em seus scripts no bash. O Bash é ótimo para pequenos scripts e oneliners, mas qualquer coisa mais complexa e é melhor escrevê-lo em Perl.
Observe que eu não testei o exposto acima, então provavelmente não funciona, mas você obtém a idéia geral.
options
no final não está correto, ele retornará -bash: syntax error near unexpected token $@
. Chame como options "$@"
.
while
condição não deveria ser em (($#))
vez disso?
$#
? Edit: você está certo. Corrigidowhile (( "$#" ))
getopt
sempre deve ser verificado como GNU getopt antes de você usá-lo, mas você não deve usá-lo de qualquer maneira, poisgetopts
é mais portátil (e geralmente melhor) de qualquer maneira. Se você fazer necessidade de chamá-lo por algum motivo, chamá-lo de uma forma específica de GNU, e garantir queGETOPT_COMPATIBLE
não está no ambiente.