Yanıtlar:
Kullanın getopts
.
POSIX özelliklerinde olduğu gibi oldukça taşınabilir. Maalesef uzun seçenekleri desteklemiyor.
Ayrıca bu bak getopts
öğretici wiki bash-hacker nezaket ve bu soruyu stackoverflow dan.
Yalnızca kısa seçeneklere ihtiyacınız varsa getopts
(sessiz olmayan hata bildirimi kullanarak) için tipik kullanım şekli :
# 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
?
:
Bir seçenek mektubundan sonra, bir argüman gerektirdiğini belirtir. :
İlk karakter olarak A , hata mesajlarını bastırmak anlamına gelir.
Sanırım bash ya da benzerini kullanıyorsun. Bir örnek:
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[@]}" "$@"
+=
Dizi ile kullanmak için +1 . Bunu yapabileceğini bilmiyordum. Güzel!
Parametreleri ayrıştırmak için bir döngü yazmanız gerekir. Gerçekten de getopts
kolayca yapmak için komutu kullanabilirsiniz .
Bu, getopts
manuel sayfadan basit bir örnektir :
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" "$*"
Geçenlerde çok yönlü ve herhangi bir sırada birden fazla anahtar türü için izin verilen iş için bir senaryo yazdım. Tam senaryoyu bariz yasal nedenlerle açıklayamıyorum (şu anda yanımda olmadığını söylemiyorum), ama işte et .. bir alt rutine koyabilir ve sonunda çağırabilirsiniz betiğinizin:
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
Ben bash betiğinizi 400 satır / 15k karakterden daha azıyla sınırlandırmanızı öneririm; bahsettiğim senaryom bu boyutu aştı ve üzerinde çalışılması oldukça zorlaştı. Görev için çok daha uygun olan Perl'de yeniden yazmaya başladım. Betikte senaryolarınız üzerinde çalışırken bunu aklınızda bulundurun. Bash küçük scriptler ve onelinerler için harikadır, ancak daha karmaşık bir şeydir ve Perl'de yazmanız daha iyi olur.
Not, yukarıdakileri test etmedim, bu yüzden muhtemelen işe yaramaz, ancak genel fikri ondan alırsınız.
options
Sonunda arama şekliniz doğru değil, geri dönecektir -bash: syntax error near unexpected token $@
. Olarak adlandırın options "$@"
.
while
koşul olmamalı (($#))
mı?
$#
? Düzenleme: haklısın. Sabitwhile (( "$#" ))
getopt
önce her zaman GNU getopt olarak doğrulanması gerektiği belirtilmelidir , ancak yine degetopts
daha taşınabilir (ve genellikle daha güzel) olduğu gibi kullanmamalısınız . Eğer varsa yapmak nedense aramak gereğini, bir GNU özgü bir şekilde diyoruz ve eminGETOPT_COMPATIBLE
ortamda değil.