Je ne sais pas getopt
mais la fonction getopts
intégrée ne peut être utilisée que pour gérer de longues options comme ceci:
while getopts :-: o
do case "$o$OPTARG" in
(-longopt1) process ;;
(-longopt2) process ;;
esac; done
Bien sûr, en l'état, cela ne fonctionne pas si les options longues sont censées avoir des arguments. Cela peut être fait, cependant, mais, comme je l'ai appris en travaillant là-dessus. Bien que je l'ai initialement inclus ici, j'ai réalisé que pour les options longues, il n'avait pas beaucoup d'utilité. Dans ce cas, cela ne faisait que raccourcir mes case
(match)
champs d'un seul caractère prévisible. Maintenant, ce que je sais, c'est qu'il est excellent pour les options courtes - il est plus utile lorsqu'il fait une boucle sur une chaîne de longueur inconnue et sélectionne des octets uniques en fonction de sa chaîne d'options. Mais lorsque l'option est l'argument, vous ne faites pas grand-chose avec une for var do case $var in
combinaison qu'elle pourrait faire. Il vaut mieux, je pense, rester simple.
Je soupçonne qu'il en va de même, getopt
mais je n'en sais pas assez pour le dire avec certitude. Étant donné le tableau d'arguments suivant, je vais démontrer mon propre petit analyseur d'arguments - qui dépend principalement de la relation d'évaluation / affectation que j'ai appris à apprécier pour alias
et $((shell=math))
.
set -- this is ignored by default --lopt1 -s 'some '\''
args' here --ignored and these are ignored \
--alsoignored andthis --lopt2 'and
some "`more' --lopt1 and just a few more
C'est la chaîne d'argument avec laquelle je vais travailler. Maintenant:
aopts() { env - sh -s -- "$@"
} <<OPTCASE 3<<\OPTSCRIPT
acase() case "\$a" in $(fmt='
(%s) f=%s; aset "?$(($f)):";;\n'
for a do case "$a" in (--) break;;
(--*[!_[:alnum:]]*) continue;;
(--*) printf "$fmt" "$a" "${a#--}";;
esac;done;printf "$fmt" '--*' ignored)
(*) aset "" "\$a";;esac
shift "$((SHIFT$$))"; f=ignored; exec <&3
OPTCASE
aset() { alias "$f=$(($f${1:-=$(($f))+}1))"
[ -n "${2+?}" ] && alias "${f}_$(($f))=$2"; }
for a do acase; done; alias
#END
OPTSCRIPT
Cela traite le tableau arg de deux manières différentes selon que vous lui remettez un ou deux ensembles d'arguments séparés par le --
délimiteur. Dans les deux cas, il s'applique aux séquences de traitement du tableau arg.
Si vous l'appelez comme:
: $((SHIFT$$=3)); aopts --lopt1 --lopt2 -- "$@"
Son premier ordre du jour sera d'écrire sa acase()
fonction pour ressembler à:
acase() case "$a" in
(--lopt1) f=lopt1; aset "?$(($f)):";;
(--lopt2) f=lopt2; aset "?$(($f)):";;
(--*) f=ignored; aset "?$(($f)):";;
(*) aset "" "$a";;esac
Et à côté de shift 3
. La substitution de commande dans la acase()
définition de la fonction est évaluée lorsque le shell appelant crée les documents d'entrée de la fonction ici, mais acase()
n'est jamais appelée ou définie dans le shell appelant. Il est appelé dans le sous-shell, bien sûr, et donc de cette façon, vous pouvez spécifier dynamiquement les options d'intérêt sur la ligne de commande.
Si vous lui donnez un tableau non délimité, il remplit simplement acase()
avec des correspondances pour tous les arguments commençant par la chaîne --
.
La fonction effectue pratiquement tout son traitement dans le sous-shell - sauvegarde itérativement chacune des valeurs de l'argument dans des alias attribués avec des noms associatifs. Une alias
fois terminé, il imprime toutes les valeurs enregistrées avec - qui est spécifié par POSIX pour imprimer toutes les valeurs enregistrées citées de telle manière que leurs valeurs puissent être réintroduites dans le shell. Alors quand je fais ...
aopts --lopt1 --lopt2 -- "$@"
Sa sortie ressemble à ceci:
...ignored...
lopt1='8'
lopt1_1='-s'
lopt1_2='some '\'' args'
lopt1_3='here'
lopt1_4='and'
lopt1_5='just'
lopt1_6='a'
lopt1_7='few'
lopt1_8='more'
lopt2='1'
lopt2_1='and
some "`more'
En parcourant la liste d'arguments, il vérifie la correspondance avec le bloc de cas. S'il y trouve une correspondance, il lance un drapeau - f=optname
. Jusqu'à ce qu'il trouve à nouveau une option valide, il ajoutera chaque argument suivant à un tableau qu'il construit en fonction de l'indicateur actuel. Si la même option est spécifiée plusieurs fois, les résultats sont composés et ne remplacent pas. Tout ce qui n'est pas au cas où - ou tout argument suivant des options ignorées - est affecté à un tableau ignoré .
La sortie est protégée par le shell pour une entrée de shell automatiquement par le shell, et donc:
eval "$(: $((SHIFT$$=3));aopts --lopt1 --lopt2 -- "$@")"
... devrait être parfaitement sûr. Si, pour une raison quelconque, il n'est pas sûr, vous devez probablement déposer un rapport de bogue auprès de votre responsable du shell.
Il attribue deux types de valeurs d'alias pour chaque correspondance. Tout d'abord, il définit un indicateur - cela se produit, qu'une option précède ou non les arguments non correspondants. Ainsi, toute occurrence de --flag
dans la liste arg se déclenchera flag=1
. Cela n'aggrave pas - --flag --flag --flag
obtient juste flag=1
. Cette valeur ne se incrément - pour tous les arguments qui pourraient le suivre. Il peut être utilisé comme clé d'index. Après avoir fait ce qui eval
précède, je peux faire:
printf %s\\n "$lopt1" "$lopt2"
...obtenir...
8
1
Et donc:
for o in lopt1 lopt2
do list= i=0; echo "$o = $(($o))"
while [ "$((i=$i+1))" -le "$(($o))" ]
do list="$list $o $i \"\${${o}_$i}\" "
done; eval "printf '%s[%02d] = %s\n' $list"; done
PRODUCTION
lopt1 = 8
lopt1[01] = -s
lopt1[02] = some ' args
lopt1[03] = here
lopt1[04] = and
lopt1[05] = just
lopt1[06] = a
lopt1[07] = few
lopt1[08] = more
lopt2 = 1
lopt2[01] = and
some "`more
Et aux arguments qui ne correspondent pas, je remplacerais ignoré dans le for ... in
champ ci-dessus pour obtenir:
ignored = 10
ignored[01] = this
ignored[02] = is
ignored[03] = ignored
ignored[04] = by
ignored[05] = default
ignored[06] = and
ignored[07] = these
ignored[08] = are
ignored[09] = ignored
ignored[10] = andthis
getopts
, mais vous utilisez la/usr/bin/getopt
commande.