Il y a une command getopt
dans la command line bash. getopt
peut être utilisé avec des options courtes (comme getopt -o axby "$@"
), et peut être utilisé avec des options courtes et longues (comme getopt -o axby -l long-key -- "$@"
), mais maintenant je n'ai besoin que de longues options (c.-à-d. les options courtes n'existent pas du tout), cependant la command getopt -l long-key -- "$@"
--long-key
pas correctement l'option --long-key
. Alors, comment puis-je utiliser la command getopt
avec seulement des options longues? Ou est-il impossible ou est-ce juste un bug de la command getopt
?
getopt
est parfaitement bien avec aucune option courte. Mais vous devez lui dire que vous n'avez pas d'options courtes. C'est une bizarrerie dans la syntaxe – du manuel:
Si aucune option
-o
ou--options
n'est trouvée dans la première partie, le premier paramètre de la deuxième partie est utilisé comme string d'options courtes.
C'est ce qui se passe dans votre test: getopt -l long-key -- --long-key foo
--long-key
getopt -l long-key -- --long-key foo
--long-key
comme la list des options -egklnoy
et foo
comme seul argument. Utilisation
getopt -o '' -l long-key -- "$@"
par exemple
$ getopt -l long-key -o '' -- --long-key foo --long-key -- 'foo' $ getopt -l long-key -o '' -- --long-key --not-recognized -n foo getopt: unrecognized option '--not-recognized' getopt: invalid option -- 'n' --long-key -- 'foo'
Dunno à propos de getopt
mais le getopts
builtin peut être utilisé pour gérer seulement les 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 j'ai appris à travailler là-dessus. Bien que je l'ai initialement inclus ici, j'ai réalisé que pour les options longues, il n'a pas beaucoup d'utilité. Dans ce cas, il ne faisait que raccourcir mes champs de case
(match)
par un seul caractère prévisible. Maintenant, ce que je sais, c'est qu'il est excellent pour les options courtes – il est très utile quand il boucle sur une string de longueur inconnue et en sélectionnant des octets uniques en fonction de sa string d'options. Mais quand l'option est l'arg, il n'y a pas beaucoup de choses que vous faites avec un for var do case $var in
combinaison que cela pourrait faire. C'est mieux, je pense, de restr simple.
Je soupçonne la même chose de getopt
mais je n'en sais pas assez pour dire avec certitude. Étant donné le tableau arg suivant, je vais démontrer mon propre petit parsingur arg – qui dépend principalement de la relation d'évaluation / d'affectation que j'ai appréciée 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 string d'arg avec laquelle je vais travailler. À présent:
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 atsortingbuez un ou deux sets 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 d'affaires sera d'écrire sa fonction acase()
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é du shift 3
. La substitution de command dans la définition de la fonction acase()
est évaluée lorsque le shell appelant construit l'input de la fonction ici-documents, mais acase()
n'est jamais appelée ou définie dans le shell appelant. Bien entendu, il est appelé dans le sous-shell, de sorte que vous pouvez spécifier dynamicment les options d'intérêt sur la command line.
Si vous lui donnez un tableau non délimité, il remplit simplement acase()
avec des correspondances pour tous les arguments commençant par la string --
.
La fonction effectue pratiquement tout son traitement dans le sous-shell – sauvegardant de manière itérative chacune des valeurs de l'arg aux alias assignés avec des noms associatifs. Quand il est à travers, il imprime toutes les valeurs qu'il a sauvegardées avec alias
– qui est POSIX – spécifié pour imprimer toutes les valeurs enregistrées de telle manière que leurs valeurs peuvent être réinjectées dans le shell. Alors quand je le 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'
Au fur et à mesure qu'il parcourt la list d'arguments, il vérifie le bloc de cas pour une correspondance. S'il trouve une correspondance, il lève un drapeau – f=optname
. Jusqu'à ce qu'il trouve à nouveau une option valide, il appenda chaque argument suivant à un tableau qu'il construit en fonction du drapeau courant. 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 dans le cas – ou tout argument suivant les options ignorées – est assigné à un tableau ignoré .
La sortie est shell-safed pour l'input shell automatiquement par le shell, et ainsi:
eval "$(: $((SHIFT$$=3));aopts --lopt1 --lopt2 -- "$@")"
… devrait être parfaitement sûr. Si pour une raison quelconque, il n'est pas sûr, vous devriez probablement déposer un rapport de bogue avec votre mainteneur de shell.
Il affecte deux types de valeurs d'alias pour chaque correspondance. Tout d'abord, il définit un drapeau – cela se produit si une option précède ou non les arguments non correspondants. Ainsi, toute occurrence de --flag
dans la list d'arguments triggersra flag=1
. Cela ne --flag --flag --flag
pas – --flag --flag --flag
obtient juste flag=1
. Cette valeur incrémente cependant – pour tous les arguments qui pourraient le suivre. Il peut être utilisé comme une key d'index. Après avoir fait l' eval
ci-dessus, je peux faire:
printf %s\\n "$lopt1" "$lopt2"
…get…
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
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 pour les arguments qui ne correspondaient pas je substituerais ignoré dans ce qui précède for ... in
champ pour get:
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