Je souhaite que des formes longues et courtes d'options de ligne de commande soient invoquées à l'aide de mon script shell.
Je sais que cela getopts
peut être utilisé, mais comme en Perl, je n'ai pas pu faire de même avec shell.
Toutes les idées sur la façon dont cela peut être fait, afin que je puisse utiliser des options telles que:
./shell.sh --copyfile abc.pl /tmp/
./shell.sh -c abc.pl /tmp/
Dans ce qui précède, les deux commandes signifient la même chose pour mon shell, mais en utilisant getopts
, je n'ai pas pu les implémenter?
bash
command-line-arguments
getopt
getopts
gagneet
la source
la source
Réponses:
Trois implémentations peuvent être envisagées:
Bash intégré
getopts
. Cela ne prend pas en charge les noms d'options longs avec le préfixe à double tiret. Il ne prend en charge que les options à un seul caractère.Implémentation BSD UNIX de la
getopt
commande autonome (c'est ce que MacOS utilise). Cela ne prend pas non plus en charge les options longues.Implémentation GNU autonome
getopt
. GNUgetopt(3)
(utilisé par la ligne de commandegetopt(1)
sous Linux) prend en charge l'analyse des options longues.Certaines autres réponses montrent une solution pour utiliser la commande bash
getopts
pour imiter les options longues. Cette solution fait en fait une option courte dont le caractère est "-". Vous obtenez donc "-" comme drapeau. Ensuite, tout ce qui suit qui devient OPTARG, et vous testez l'OPTARG avec un imbriquécase
.C'est intelligent, mais il comporte des mises en garde:
getopts
ne peut pas appliquer la spécification opt. Il ne peut pas renvoyer d'erreurs si l'utilisateur fournit une option non valide. Vous devez faire votre propre vérification des erreurs pendant que vous analysez OPTARG.Ainsi, bien qu'il soit possible d'écrire plus de code pour contourner le manque de prise en charge des options longues, cela représente beaucoup plus de travail et va partiellement à l'encontre du but d'utiliser un analyseur getopt pour simplifier votre code.
la source
getopt
etgetopts
sont des bêtes différentes, et les gens semblent avoir un peu de malentendu sur ce qu'ils font.getopts
est une commande intégrée permettantbash
de traiter les options de ligne de commande dans une boucle et d'affecter tour à tour chaque option et valeur trouvées aux variables intégrées, afin que vous puissiez les traiter davantage.getopt
, cependant, est un programme utilitaire externe, et il ne traite pas réellement vos options pour vous comme le font par exemple bashgetopts
, leGetopt
module Perl ou Pythonoptparse
/argparse
modules. Tout cegetopt
qui est fait est de canoniser les options qui sont passées - c'est-à-dire les convertir en une forme plus standard, afin qu'il soit plus facile pour un script shell de les traiter. Par exemple, une application degetopt
pourrait convertir les éléments suivants:en cela:
Vous devez effectuer vous-même le traitement. Vous ne devez pas utiliser
getopt
du tout si vous faites diverses restrictions sur la façon dont vous pouvez spécifier les options:-o
ci-dessus), la valeur doit aller comme un argument séparé (après un espace).Pourquoi utiliser
getopt
au lieu degetopts
? La raison fondamentale est que seul GNUgetopt
vous permet de prendre en charge les options de ligne de commande portant un nom long. 1 (GNUgetopt
est la valeur par défaut sous Linux. Mac OS X et FreeBSD sont livrés avec une version basique et pas très utilegetopt
, mais la version GNU peut être installée; voir ci-dessous.)Par exemple, voici un exemple d'utilisation de GNU
getopt
, à partir d'un de mes scripts appeléjavawrap
:Cela vous permet de spécifier des options similaires
--verbose -dm4096 --minh=20 --maxhe 40 --debugfi="/Users/John Johnson/debug.txt"
ou similaires. L'appel à agetopt
pour effet de canoniser les options pour--verbose -d -m 4096 --minheap 20 --maxheap 40 --debugfile "/Users/John Johnson/debug.txt"
que vous puissiez les traiter plus facilement. La citation autour"$1"
et"$2"
est importante car elle garantit que les arguments avec des espaces sont traités correctement.Si vous supprimez les 9 premières lignes (tout en haut de la
eval set
ligne), le code fonctionnera toujours ! Cependant, votre code sera beaucoup plus pointilleux dans les types d'options qu'il accepte: En particulier, vous devrez spécifier toutes les options sous la forme "canonique" décrite ci-dessus.getopt
Cependant, avec l'utilisation de , vous pouvez regrouper des options à une seule lettre, utiliser des formes non ambiguës plus courtes d'options longues, utiliser le style--file foo.txt
ou--file=foo.txt
, utiliser le style-m 4096
ou-m4096
, mélanger les options et les non-options dans n'importe quel ordre, etc.getopt
génère également un message d'erreur si des options non reconnues ou ambiguës sont trouvées.REMARQUE : Il existe en fait deux versions totalement différentes de
getopt
, de basegetopt
et GNUgetopt
, avec des fonctionnalités différentes et des conventions d'appel différentes. 2 Basicgetopt
est assez cassé: non seulement il ne gère pas les options longues, mais il ne peut même pas gérer les espaces incorporés à l'intérieur des arguments ou des arguments vides, alorsgetopts
qu'il le fait correctement. Le code ci-dessus ne fonctionnera pas en basegetopt
. GNUgetopt
est installé par défaut sous Linux, mais sous Mac OS X et FreeBSD, il doit être installé séparément. Sur Mac OS X, installez MacPorts ( http://www.macports.org ), puissudo port install getopt
installez GNUgetopt
(généralement dans/opt/local/bin
) et assurez-vous qu'il se/opt/local/bin
trouve dans votre chemin de shell avant/usr/bin
. Sur FreeBSD, installezmisc/getopt
.Un guide rapide pour modifier l'exemple de code pour votre propre programme: Sur les premières lignes, tout est "passe-partout" qui doit rester le même, sauf la ligne qui appelle
getopt
. Vous devez modifier le nom du programme après-n
, spécifier les options courtes après-o
et les options longues après--long
. Mettez deux points après les options qui prennent une valeur.Enfin, si vous voyez du code qui vient de
set
remplacereval set
, il a été écrit pour BSDgetopt
. Vous devriez le changer pour utiliser leeval set
style, qui fonctionne bien avec les deux versions degetopt
, tandis que le clairset
ne fonctionne pas correctement avec GNUgetopt
.1 En fait,
getopts
inksh93
prend en charge les options nommées depuis longtemps, mais ce shell n'est pas utilisé aussi souvent quebash
. Danszsh
, utilisezzparseopts
pour obtenir cette fonctionnalité.2 Techniquement, «GNU
getopt
» est un terme impropre; cette version a été écrite pour Linux plutôt que pour le projet GNU. Cependant, il suit toutes les conventions GNU, et le terme "GNUgetopt
" est couramment utilisé (par exemple sur FreeBSD).la source
getopt
sous Linux n'est pas un utilitaire GNU et le traditionnelgetopt
ne vient pas initialement de BSD mais d'AT & T Unix. ksh93getopts
(également d'AT & T) prend en charge les options longues de style GNU.POSIXLY_CORRECT
), tandis que "Linux-Enhanced Getopt" suggère à tort que cette version n'existe que sur Linux.getopt
pourrait facilement être porté sur d'autres Unices, mais de nombreux autres logicielsutil-linux
sont spécifiques à Linux). Tous les programmes non GNU utilisant GNU getopt (3) le comprennent$POSIX_CORRECT
. Par exemple, vous ne diriez pas queaplay
c'est GNU uniquement pour ces raisons. Je soupçonne que lorsque FreeBSD mentionne GNU getopt, cela signifie l'API GNU getopt (3) C.getopt
util, pas à getopt (3).La fonction intégrée getopts de Bash peut être utilisée pour analyser les options longues en plaçant un caractère tiret suivi de deux points dans l'optspec:
Après avoir copié dans le fichier exécutable nom =
getopts_test.sh
dans le répertoire de travail courant , on peut produire une sortie commeDe toute évidence, getopts n'effectue ni
OPTERR
vérification ni analyse d'arguments d'option pour les options longues. Le fragment de script ci-dessus montre comment cela peut être fait manuellement. Le principe de base fonctionne également dans le shell Debian Almquist ("tiret"). Notez le cas particulier:Notez que, comme le souligne GreyCat sur http://mywiki.wooledge.org/BashFAQ , cette astuce exploite un comportement non standard du shell qui autorise l'argument option (c'est-à-dire le nom de fichier dans "-f filename") à concaténer à l'option (comme dans "-nomfichier"). Le standard POSIX dit qu'il doit y avoir un espace entre eux, ce qui dans le cas de "- longoption" mettrait fin à l'analyse des options et transformerait toutes les options longues en arguments sans option.
la source
!
inval="${!OPTIND}
?getopts
incrémente automatiquement uniquementOPTIND
avec 1, mais dans notre cas, nous en avons besoin pour incrémenter de 2, nous l'incrémentons donc de 1 manuellement, puis laissons l'getopts
incrémenter de 1 pour nous automatiquement.$
nécessaire.OPTIND=$(( $OPTIND + 1 ))
peut être justeOPTIND=$(( OPTIND + 1 ))
. Encore plus intéressant, vous pouvez même affecter et augmenter des variables à l'intérieur d'une expression arithmétique, il est donc possible de l'abréger davantage: $(( ++OPTIND ))
, ou même de(( ++OPTIND ))
prendre en compte ce qui++OPTIND
sera toujours positif, de sorte qu'il ne déclenchera pas une exécution de shell avec l'-e
option. :-) gnu.org/software/bash/manual/html_node/Shell-Arithmetic.html--very-bad
donne pas d' avertissement?La
getopts
commande intégrée est toujours, AFAIK, limitée aux options à un seul caractère.Il existe (ou existait auparavant) un programme externe
getopt
qui réorganiserait un ensemble d'options de sorte qu'il serait plus facile à analyser. Vous pouvez également adapter cette conception pour gérer de longues options. Exemple d'utilisation:Vous pouvez utiliser un schéma similaire avec une
getoptlong
commande.Notez que la faiblesse fondamentale du
getopt
programme externe est la difficulté de gérer les arguments contenant des espaces et de conserver ces espaces avec précision. C'est pourquoi la fonction intégréegetopts
est supérieure, bien que limitée par le fait qu'elle ne gère que les options à une seule lettre.la source
eval set
avec des guillemets (voir ma réponse ci-dessous) afin qu'il fonctionne également correctement avec GNU getopt (la valeur par défaut sous Linux) et gère correctement les espaces.${1+"$@"}
est étrange et en contradiction avec ce qui est nécessaire dans les shells modernes et spécifiquement avec n'importe quel shell que vous trouveriez sur Linux. Voir Utilisation de $ 1: + "$ @"} dans / bin / sh pour un discussion de cette notation.)eval set
fait la bonne chose avec GNU et BSDgetopt
, alors que plain faitset
seulement la bonne chose avec BSDgetopt
. Vous pouvez donc aussi utilisereval set
pour encourager les gens à prendre l'habitude de le faire. BTW merci, je ne savais pas que ce${1+"$@"}
n'était plus nécessaire. Je dois écrire des choses qui fonctionnent à la fois sur Mac OS X et Linux - entre les deux, elles forcent beaucoup de portabilité. Je viens de vérifier et"$@"
ne le fait en effet la bonne chose sur toussh
,bash
,ksh
etzsh
sous Mac OS X; sûrement sous Linux aussi.Voici un exemple qui utilise réellement getopt avec de longues options:
la source
eval set
avec des guillemets (voir ma réponse ci-dessous) afin qu'il fonctionne également correctement avec GNU getopt (la valeur par défaut sous Linux) et gère correctement les espaces.getopt
alors que la question concernegetopts
.(--
- ils(-*
et(*
valides? En quoi sont-ils différents de--
,-*
et*
?(--)
est donc identique à celle--)
d'unecase
strophe. Il est étrange de voir l'indentation inégale et l'utilisation incohérente de cette parenthèse facultative, mais le code actuel de la réponse me semble valide.Les options longues peuvent être analysées par le
getopts
module intégré standard en tant qu '«arguments» de-
«l'option»Il s'agit d'un shell POSIX portable et natif - aucun programme externe ni bashism n'est nécessaire.
Ce guide implémente les options longues comme arguments de l'
-
option, il--alpha
est donc vugetopts
comme-
avec argumentalpha
et--bravo=foo
est vu comme-
avec argumentbravo=foo
. L'argument vrai peut être récolté avec un simple remplacement:${OPTARG#*=}
.Dans cet exemple,
-b
et-c
(et leurs formes longues,--bravo
et--charlie
) ont des arguments obligatoires. Les arguments pour les options longues viennent après des signes égaux, par exemple--bravo=foo
(les délimiteurs d'espace pour les options longues seraient difficiles à implémenter, voir ci-dessous).Parce que cela utilise la fonction
getopts
intégrée , cette solution prend en charge l'utilisation commecmd --bravo=foo -ac FILE
(qui a combiné des options-a
et-c
et entrelace des options longues avec des options standard) tandis que la plupart des autres réponses ici ont du mal ou échouent à le faire.Lorsque l'option est un tiret (
-
), c'est une option longue.getopts
aura analysé l'option réelle réelle$OPTARG
, par exemple, à l'--bravo=foo
origine les ensemblesOPT='-'
etOPTARG='bravo=foo'
. Laif
strophe définit$OPT
le contenu de$OPTARG
avant le premier signe égal (bravo
dans notre exemple), puis le supprime depuis le début de$OPTARG
(donnant=foo
cette étape, ou une chaîne vide s'il n'y en a pas=
). Enfin, nous supprimons l'argument principal=
. À ce stade,$OPT
est soit une option courte (un caractère), soit une option longue (2+ caractères).L'
case
option correspond alors aux options courtes ou longues. Pour les options courtes,getopts
se plaint automatiquement des options et des arguments manquants, nous devons donc les répliquer manuellement à l'aide duneeds_arg
fonction, qui se ferme fatalement lorsqu'elle$OPTARG
est vide. La??*
condition correspondra à toute option longue restante (?
correspond à un seul caractère et*
correspond à zéro ou plus, donc??*
correspond à 2+ caractères), ce qui nous permet d'émettre l'erreur "Option illégale" avant de quitter.(Remarque sur les noms de variables en majuscules: en général, le conseil est de réserver des variables en majuscules à l'utilisation du système. Je garde
$OPT
que tout en majuscules pour le maintenir en ligne avec$OPTARG
., Mais cela ne rompt cette convention , je pense qu'il convient car c'est quelque chose que le système aurait dû faire, et il devrait être sûr car il n'y a pas de normes (afaik) qui utilisent une telle variable.)Pour vous plaindre d'arguments inattendus sur les options longues, imitez ce que nous avons fait pour les arguments obligatoires: utilisez une fonction d'assistance. Il suffit de retourner le test pour se plaindre d'un argument alors que l'on n'est pas attendu:
Une ancienne version de cette réponse avait tenté d'accepter des options longues avec des arguments délimités par des espaces, mais elle n'était pas fiable;
getopts
pourrait se terminer prématurément en supposant que l'argument dépassait sa portée et que l'incrémentation manuelle$OPTIND
ne fonctionne pas dans tous les shells.Cela serait accompli en utilisant l'une de ces techniques:
eval "bravo=\"\$$OPTIND\""
bravo="${!OPTIND}"
P
Zsh :bravo="${(P)OPTIND}"
puis a conclu avec quelque chose comme
[ $# -gt $OPTIND ] && OPTIND=$((OPTIND+1))
la source
letter-c
ne nécessitant aucun argument, ne serait-il pas suffisant de l'utiliserletter-c)
?; le*
semble redondant.getopts
s'arrête au premier argument positionnel car il n'est pas conçu pour les traiter. Cela permet aux sous-commandes avec leurs propres arguments, par exemplegit diff --color
, donc j'interpréteraiscommand --foo=moo bar --baz waz
comme ayant--foo
comme argumentcommand
et--baz waz
comme argument (avec option) labar
sous-commande. Cela peut être fait avec le code ci-dessus. Je rejette--bravo -blah
parce que--bravo
nécessite un argument et il n'est pas clair que ce-blah
ne soit pas une autre option.eval
dans le shell POSIX, il est répertorié sous le reste de la réponse.Jetez un œil à shFlags qui est une bibliothèque de shell portable (ce qui signifie: sh, bash, dash, ksh, zsh sous Linux, Solaris, etc.).
Il rend l'ajout de nouveaux indicateurs aussi simple que l'ajout d'une ligne à votre script, et il fournit une fonction d'utilisation générée automatiquement.
Voici un simple
Hello, world!
utilisant shFlag :Pour les systèmes d'exploitation qui ont le getopt amélioré qui prend en charge les options longues (par exemple Linux), vous pouvez faire:
Pour le reste, vous devez utiliser l'option courte:
L'ajout d'un nouveau drapeau est aussi simple que l'ajout d'un nouveau
DEFINE_ call
.la source
Utilisation
getopts
avec des options et des arguments courts / longsFonctionne avec toutes les combinaisons, par exemple:
Quelques déclarations pour cet exemple
A quoi ressemblerait la fonction Usage
getops
avec des drapeaux longs / courts ainsi que des arguments longsProduction
Combiner ce qui précède dans un script cohérent
la source
eval
approche des arguments espacés sur les options longues et je l'ai trouvée peu fiable avec certains shells (bien que je m'attende à ce que cela fonctionne avec bash, auquel cas vous n'avez pas à utilisereval
). Voir ma réponse pour savoir comment accepter des arguments d'option longs avec=
et mes tentatives notées pour utiliser l'espace. Ma solution ne fait pas d'appels externes alors que celle-ci utilisecut
plusieurs fois.Autrement...
la source
$args
réaffectation? Cela pourrait même être fait sans bashismes, mais ce code perdra des espaces dans les options et les arguments (je ne pense pas que l'$delim
astuce fonctionnera). Vous pouvez à la place exécuterset
à l' intérieur de lafor
boucle si vous êtes assez prudent pour la vider uniquement sur la première itération. Voici une version plus sûre sans bashismes.J'ai en quelque sorte résolu de cette façon:
Suis-je stupide ou quelque chose?
getopt
etgetopts
sont tellement déroutants.la source
-ltr
ou-lt -r
aussi-l -t -r
). Et il fournit également une gestion des erreurs et un moyen facile de décaler les paramètres traités une fois le traitement des options terminé.Dans le cas où vous ne voulez pas la
getopt
dépendance, vous pouvez le faire:Bien sûr, vous ne pouvez pas utiliser les options de style longues avec un seul tiret. Et si vous souhaitez ajouter des versions raccourcies (par exemple --verbos au lieu de --verbose), vous devez les ajouter manuellement.
Mais si vous cherchez à obtenir des
getopts
fonctionnalités avec de longues options, c'est un moyen simple de le faire.J'ai également mis cet extrait dans un sens .
la source
--)
il semble y avoir unshift ;
manquant. Pour le moment, le--
reste comme premier argument non optionnel.--
option a besoin d'unshift
dedans. Je dis que c'est mieux parce que les alternatives sont des versions dépendantes de la plate-forme degetopt
ougetopts_long
ou vous devez forcer les options courtes à être utilisées uniquement au début de la commande (c'est-à-dire - vous utilisezgetopts
puis traitez les options longues ensuite), alors que cela donne n'importe quel ordre et un contrôle complet.Le intégré
getopts
ne peut pas faire cela. Il existe un programme externe getopt (1) qui peut le faire, mais vous ne l'obtenez que sur Linux à partir du package util-linux . Il est livré avec un exemple de script getopt-parse.bash .Il existe également une
getopts_long
fonction shell écrite.la source
getopt
été inclus dans FreeBSD version 1.0 en 1993, et fait partie de FreeBSD depuis lors. En tant que tel, il a été adopté à partir de FreeBSD 4.x pour être inclus dans le projet Darwin d'Apple. Depuis OS X 10.6.8, la page de manuel incluse par Apple reste un duplicata exact de la page de manuel FreeBSD. Alors oui, il est inclus dans OS X et les autres systèmes d'exploitation à côté de Linux. -1 sur cette réponse pour la désinformation..
la source
"${1:0:1}"
pour l'argument # 1, sous-chaîne à l'index 0, longueur 1. Cela ne permet pas de mélanger les options courtes et longues.Dans
ksh93
,getopts
prend en charge les noms longs ...Ou du moins les tutoriels que j'ai trouvés l'ont dit. Essayez-le et voyez.
la source
Je n'écris que des scripts shell de temps en temps et je ne pratique plus, donc tout commentaire est apprécié.
En utilisant la stratégie proposée par @Arvid Requate, nous avons remarqué quelques erreurs utilisateur. Un utilisateur qui oublie d'inclure une valeur verra accidentellement le nom de l'option suivante traité comme une valeur:
entraînera la valeur de "loglevel" comme "--toc = TRUE". Cela peut être évité.
J'ai adapté quelques idées sur la vérification des erreurs utilisateur pour CLI à partir de la discussion http://mwiki.wooledge.org/BashFAQ/035 sur l'analyse manuelle. J'ai inséré la vérification des erreurs dans la gestion des arguments "-" et "-".
Ensuite, j'ai commencé à jouer avec la syntaxe, donc toutes les erreurs ici sont strictement de ma faute, pas les auteurs originaux.
Mon approche aide les utilisateurs qui préfèrent entrer longtemps avec ou sans signe égal. Autrement dit, il devrait avoir la même réponse à "--loglevel 9" que "--loglevel = 9". Dans la méthode - / space, il n'est pas possible de savoir avec certitude si l'utilisateur oublie un argument, il est donc nécessaire de deviner.
Au cas où vous commenceriez sur ce point, il existe une différence intéressante entre les formats "--opt = value" et "--opt value". Avec le signe égal, l'argument de ligne de commande est considéré comme "opt = valeur" et le travail à gérer qui est l'analyse de chaîne, à séparer au niveau "=". En revanche, avec "--opt value", le nom de l'argument est "opt" et nous avons le défi d'obtenir la prochaine valeur fournie dans la ligne de commande. C'est là que @Arvid Requate a utilisé $ {! OPTIND}, la référence indirecte. Je ne comprends toujours pas cela, enfin, et les commentaires dans BashFAQ semblent mettre en garde contre ce style ( http://mywiki.wooledge.org/BashFAQ/006 ). BTW, je ne pense pas que les commentaires de l'affiche précédente sur l'importance de OPTIND = $ (($ OPTIND + 1)) sont corrects. Je veux dire,
Dans la dernière version de ce script, l'indicateur -v signifie l'impression VERBOSE.
Enregistrez-le dans un fichier appelé "cli-5.sh", rendez-le exécutable, et l'un d'eux fonctionnera ou échouera de la manière souhaitée
Voici un exemple de sortie de la vérification des erreurs sur l'utilisateur intpu
Vous devriez envisager d'activer -v, car il imprime les composants internes d'OPTIND et d'OPTARG
la source
OPTIND=$(( $OPTIND + 1 ))
: il est nécessaire chaque fois que vous 'engloutissez' le paramètre OPTIND (par exemple: lorsque l'un est utilisé--toc value
: la valeur est dans le numéro de paramètre $ OPTIND. Une fois que vous l'avez récupéré pour la valeur de toc, vous devez dire à getopts que le prochain paramètre à analyser n'est pas une valeur, mais celui qui le suit (d'où le :.OPTIND=$(( $OPTIND + 1 ))
et votre script (ainsi que le scriptshift $(( $OPTIND -1 ))
auquel vous vous référez) sont manquants, après le done: (comme getopts est sorti après avoir analysé les paramètres 1 en OPTIND-1, vous devez les déplacer afin$@
est maintenant tout paramètre "non-options" restantInventer une autre version de la roue ...
Cette fonction est (espérons-le) un remplacement de shell bourne simple compatible POSIX pour getopt GNU. Il prend en charge les options courtes / longues qui peuvent accepter des arguments obligatoires / facultatifs / aucun argument, et la façon dont les options sont spécifiées est presque identique à GNU getopt, donc la conversion est triviale.
Bien sûr, c'est encore un gros morceau de code à insérer dans un script, mais c'est environ la moitié des lignes de la fonction shell getopt_long bien connue, et cela pourrait être préférable dans les cas où vous souhaitez simplement remplacer les utilisations existantes de getopt GNU.
Ceci est un code assez nouveau, donc YMMV (et certainement, faites-moi savoir si ce n'est pas réellement compatible POSIX pour une raison quelconque - la portabilité était l'intention dès le départ, mais je n'ai pas d'environnement de test POSIX utile).
Le code et l'exemple d'utilisation suivent:
Exemple d'utilisation:
la source
La réponse acceptée fait un très bon travail en soulignant toutes les lacunes de bash intégré
getopts
. La réponse se termine par:Et même si je suis d'accord en principe avec cette affirmation, je pense que le nombre de fois où nous avons tous implémenté cette fonctionnalité dans divers scripts justifie de mettre un peu d'effort dans la création d'une solution "standardisée" et bien testée.
En tant que tel, j'ai "mis à niveau" bash intégré en l'
getopts
implémentantgetopts_long
dans pure bash, sans dépendances externes. L'utilisation de la fonction est 100% compatible avec la fonction intégréegetopts
.En incluant
getopts_long
(qui est hébergé sur GitHub ) dans un script, la réponse à la question d'origine peut être implémentée aussi simplement que:la source
Je n'ai pas encore assez de représentants pour commenter ou voter sa solution, mais la réponse de Sme a extrêmement bien fonctionné pour moi. Le seul problème que j'ai rencontré est que les arguments finissent par être entre guillemets simples (j'ai donc une bande à retirer).
J'ai également ajouté quelques exemples d'utilisations et du texte d'aide. Je vais inclure ma version légèrement étendue ici:
la source
Ici vous pouvez trouver quelques approches différentes pour l'analyse d'options complexes dans bash: http://mywiki.wooledge.org/ComplexOptionParsing
J'ai créé le suivant, et je pense que c'est un bon, car c'est un code minimal et les options longues et courtes fonctionnent. Une option longue peut également avoir plusieurs arguments avec cette approche.
la source
Je travaille sur ce sujet depuis assez longtemps ... et j'ai créé ma propre bibliothèque dont vous aurez besoin de vous approvisionner dans votre script principal. Voir libopt4shell et cd2mpc pour un exemple. J'espère que cela aide !
la source
Une solution améliorée:
la source
Il est peut-être plus simple d'utiliser ksh, juste pour la partie getopts, si vous avez besoin de longues options de ligne de commande, car cela peut être plus facile.
la source
Je voulais quelque chose sans dépendances externes, avec un support bash strict (-u), et j'en avais besoin pour fonctionner même sur les anciennes versions bash. Cela gère différents types de paramètres:
Insérez simplement ce qui suit en haut de votre script:
Et utilisez-le comme ceci:
la source
Afin de rester compatible entre les plates-formes et d'éviter la dépendance à des exécutables externes, j'ai porté du code à partir d'un autre langage.
Je le trouve très simple d'utilisation, voici un exemple:
Le BASH requis est un peu plus long qu'il ne pourrait l'être, mais je voulais éviter de me fier aux tableaux associatifs de BASH 4. Vous pouvez également le télécharger directement depuis http://nt4.com/bash/argparser.inc.sh
la source
Si toutes vos options longues ont des premiers caractères uniques et correspondants comme options courtes, par exemple
Est le même que
Vous pouvez utiliser ceci avant getopts pour réécrire $ args:
Merci pour mtvee pour l'inspiration ;-)
la source
si c'est simplement ainsi que vous voulez appeler le script
alors vous pouvez suivre ce moyen le plus simple pour y parvenir à l'aide de getopt et --longoptions
essayez ceci, j'espère que c'est utile
la source
getopts "pourrait être utilisé" pour analyser les options longues tant que vous ne vous attendez pas à ce qu'elles aient des arguments ...
Voici comment:
Si vous essayez d'utiliser OPTIND pour obtenir un paramètre pour l'option longue, getopts le traitera comme le premier paramètre de position non optionnel et cessera d'analyser tous les autres paramètres. Dans un tel cas, vous feriez mieux de le traiter manuellement avec une simple déclaration de cas.
Cela fonctionnera "toujours":
Bien que ce ne soit pas aussi flexible que getopts et vous devez faire une grande partie du code de vérification des erreurs vous-même dans les instances de cas ...
Mais c'est une option.
la source
Intégré
getopts
analyse uniquement les options courtes (sauf dans ksh93), mais vous pouvez toujours ajouter quelques lignes de script pour que getopts gère les options longues.Voici une partie du code trouvé sur http://www.uxora.com/unix/shell-script/22-handle-long-options-with-getopts
Voici un test:
Sinon, dans le récent Korn Shell ksh93, il
getopts
peut naturellement analyser les options longues et même afficher une page de manuel. (Voir http://www.uxora.com/unix/shell-script/20-getopts-with-man-page-and-long-options )la source
Th intégré dans OS X (BSD) getopt ne supporte pas les options longues, mais la version GNU fait:
brew install gnu-getopt
. Puis, quelque chose de similaire à:cp /usr/local/Cellar/gnu-getopt/1.1.6/bin/getopt /usr/local/bin/gnu-getopt
.la source
EasyOptions gère les options courtes et longues:
la source