Antworten:
Verwenden Sie getopts
.
Es ist ziemlich portabel wie in der POSIX-Spezifikation. Leider unterstützt es keine langen Optionen.
Siehe auch dieses getopts
Tutorial mit freundlicher Genehmigung des Bash-Hacker-Wikis und diese Frage von stackoverflow.
Wenn Sie nur kurze Optionen benötigen, getopts
lautet das typische Verwendungsmuster für (bei Verwendung der nicht stillen Fehlerberichterstattung):
# 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
?
:
Nach einem Optionsbuchstaben ist ein Argument erforderlich. Ein :
als erstes Zeichen bedeutet, Fehlermeldungen zu unterdrücken.
Ich nehme an, Sie verwenden Bash oder ähnliches. Ein Beispiel:
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[@]}" "$@"
+=
mit einem Array. Ich wusste nicht, dass du das machen kannst. Nett!
Sie müssen einen Zyklus schreiben, um die Parameter zu analysieren. In der Tat können Sie getopts
Befehl verwenden, um es einfach zu tun.
Dies ist ein einfaches Beispiel aus der getopts
Manualpage:
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" "$*"
Ich habe kürzlich ein Skript für die Arbeit geschrieben, das vielseitig ist und mehrere Arten von Schaltern in beliebiger Reihenfolge zulässt. Ich kann das vollständige Skript aus offensichtlichen rechtlichen Gründen nicht offenlegen (ganz zu schweigen davon, dass ich es im Moment nicht bei mir habe), aber hier ist das Fleisch davon. Sie können es in eine Unterroutine einfügen und am Ende aufrufen Ihres Skripts:
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
Ich empfehle, Ihr Bash-Skript auf weniger als 400 Zeilen / 15.000 Zeichen zu beschränken. Mein oben genanntes Drehbuch wuchs über diese Größe hinaus und es wurde sehr schwierig, daran zu arbeiten. Ich habe angefangen, es in Perl umzuschreiben, das für die Aufgabe viel besser geeignet ist. Denken Sie daran, wenn Sie in bash an Ihren Skripten arbeiten. Bash ist großartig für kleine Skripte und Oneliners, aber alles, was komplexer ist, und Sie sollten es besser in Perl schreiben.
Beachten Sie, dass ich die obigen Tests nicht durchgeführt habe, sodass sie wahrscheinlich nicht funktionieren, aber Sie erhalten eine allgemeine Vorstellung davon.
options
am Ende anrufen, ist nicht korrekt, es wird zurückkehren -bash: syntax error near unexpected token $@
. Nennen Sie es als options "$@"
.
while
Bedingung sollte nicht (($#))
stattdessen sein?
$#
? Bearbeiten: du hast recht. while (( "$#" ))
getopt
es immer als GNU getopt verifiziert werden sollte, bevor Sie es verwenden, aber Sie sollten es sowieso nicht verwenden, dagetopts
es portabler (und im Allgemeinen netter) ist. Wenn Sie tun müssen es aus irgendeinem Grund nennen, nennen Sie es in einer GNU-spezifische Art und Weise, und dafür sorgen , dassGETOPT_COMPATIBLE
nicht in die Umwelt.