Risposte:
Usa getopts
.
È abbastanza portatile come nelle specifiche POSIX. Sfortunatamente non supporta opzioni lunghe.
Vedi anche questo getopts
tutorial per gentile concessione della wiki di bash-hacker e questa domanda da StackOverflow.
Se sono necessarie solo opzioni brevi, il modello di utilizzo tipico per getopts
(utilizzando la segnalazione errori non silenziosa) è:
# 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
?
:
lettera dopo un'opzione indica che richiede un argomento. A :
come primo carattere significa sopprimere i messaggi di errore.
Presumo che tu stia usando bash o simili. Un esempio:
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[@]}" "$@"
+=
con un array. Non sapevo che potresti farlo. Bello!
Devi scrivere un ciclo per analizzare i parametri. In effetti puoi usare il getopts
comando per farlo facilmente.
Questo è un semplice esempio dalla getopts
pagina del manuale:
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" "$*"
Di recente ho scritto una sceneggiatura per un lavoro versatile che permettesse più tipi di switch in qualsiasi ordine. Non posso rivelare l'intero copione per ovvi motivi legali (per non parlare del fatto che non ce l'ho con me al momento), ma eccone il contenuto .. puoi metterlo in un sottoprogramma e chiamarlo alla fine della tua sceneggiatura:
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
Consiglio di limitare il tuo script bash a meno di 400 righe / 15k caratteri; la mia sceneggiatura di cui sopra è cresciuta oltre queste dimensioni ed è diventato molto difficile lavorarci su. Ho iniziato a riscriverlo in Perl, che è molto più adatto per l'attività. Tienilo a mente mentre lavori sui tuoi script in bash. Bash è ottimo per piccoli script e oneliner, ma qualcosa di più complesso e farai meglio a scriverlo in Perl.
Nota, non ho testato quanto sopra, quindi probabilmente non funziona, ma hai un'idea generale da esso.
options
alla fine non è corretto, tornerà -bash: syntax error near unexpected token $@
. Chiamalo come options "$@"
.
while
condizione non dovrebbe essere (($#))
invece?
$#
? Modifica: hai ragione. Risolto il problema conwhile (( "$#" ))
getopt
dovrebbe sempre essere verificato come GNU getopt prima di usarlo, ma non dovresti usarlo comunque poichégetopts
è più portatile (e generalmente più bello) comunque. Se fai bisogno di chiamarlo per qualche ragione, lo chiamano in un modo GNU-specifici, e assicurarsi cheGETOPT_COMPATIBLE
non sia nell'ambiente.