getopt
y getopts
sont des bêtes différentes, et les gens semblent avoir un peu de mal à comprendre ce qu'ils font. getopts
est une commande intégrée à bash
pour traiter les options de la ligne de commande dans une boucle et affecter chaque option et valeur trouvée à des variables intégrées, afin de pouvoir les traiter ultérieurement. getopt
est cependant un programme utilitaire externe, et il est le seul à pouvoir être utilisé. ne traite pas réellement vos options pour vous de la manière dont, par exemple, bash getopts
le langage Perl Getopt
ou le module Python optparse
/ argparse
les modules le font. Tout cela getopt
fait est de canoniser les options qui sont passées - c'est-à-dire de les convertir en une forme plus standard, afin qu'il soit plus facile pour un script shell de les traiter. Par exemple, une application de getopt
pourrait convertir ce qui suit :
myscript -ab infile.txt -ooutfile.txt
dans ceci :
myscript -a -b -o outfile.txt infile.txt
Vous devez faire le traitement vous-même. Vous n'avez pas à utiliser getopt
du tout si vous imposez diverses restrictions sur la façon dont vous pouvez spécifier les options :
- ne mettez qu'une seule option par argument ;
- toutes les options passent avant tous les paramètres positionnels (c'est-à-dire les arguments sans option) ;
- pour les options avec des valeurs (par exemple
-o
ci-dessus), la valeur doit être présentée comme un argument séparé (après un espace).
Pourquoi utiliser getopt
au lieu de getopts
? La raison principale est que seul GNU getopt
vous permet de prendre en charge les options de ligne de commande aux noms longs. 1 (GNU getopt
est la valeur par défaut sous Linux. Mac OS X et FreeBSD sont livrés avec une version basique et peu utile de l'outil de gestion de l'information. getopt
mais la version GNU peut être installée ; voir ci-dessous).
Par exemple, voici un exemple d'utilisation de GNU getopt
à partir d'un script de moi appelé javawrap
:
# NOTE: This requires GNU getopt. On Mac OS X and FreeBSD, you have to install this
# separately; see below.
TEMP=`getopt -o vdm: --long verbose,debug,memory:,debugfile:,minheap:,maxheap: \
-n 'javawrap' -- "$@"`
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"
VERBOSE=false
DEBUG=false
MEMORY=
DEBUGFILE=
JAVA_MISC_OPT=
while true; do
case "$1" in
-v | --verbose ) VERBOSE=true; shift ;;
-d | --debug ) DEBUG=true; shift ;;
-m | --memory ) MEMORY="$2"; shift 2 ;;
--debugfile ) DEBUGFILE="$2"; shift 2 ;;
--minheap )
JAVA_MISC_OPT="$JAVA_MISC_OPT -XX:MinHeapFreeRatio=$2"; shift 2 ;;
--maxheap )
JAVA_MISC_OPT="$JAVA_MISC_OPT -XX:MaxHeapFreeRatio=$2"; shift 2 ;;
-- ) shift; break ;;
* ) break ;;
esac
done
Cela vous permet de spécifier des options comme --verbose -dm4096 --minh=20 --maxhe 40 --debugfi="/Users/John Johnson/debug.txt"
ou similaire. L'effet de l'appel à getopt
est de canoniser les options en --verbose -d -m 4096 --minheap 20 --maxheap 40 --debugfile "/Users/John Johnson/debug.txt"
afin que vous puissiez les traiter plus facilement. Les citations autour de "$1"
y "$2"
est important car il garantit que les arguments contenant des espaces sont traités correctement.
Si vous supprimez les 9 premières lignes (tout ce qui va jusqu'au eval set
), le code sera toujours fonctionner ! Cependant, votre code sera beaucoup plus pointilleux quant aux types d'options qu'il accepte : En particulier, vous devrez spécifier toutes les options sous la forme "canonique" décrite ci-dessus. Avec l'utilisation de getopt
Cependant, vous pouvez regrouper des options à une seule lettre, utiliser des formes plus courtes et non ambiguës de longues options, utiliser l'option --file foo.txt
o --file=foo.txt
utilisez soit le -m 4096
o -m4096
style, mélanger des options et des non-options dans n'importe quel ordre, etc. getopt
produit également un message d'erreur si des options non reconnues ou ambiguës sont trouvées.
NOTE : Il y a en fait deux totalement différent des versions de getopt
, de base getopt
et GNU getopt
avec différentes caractéristiques et différentes conventions d'appel. 2 Base getopt
est bien 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 les arguments vides, alors que getopts
fait bien les choses. Le code ci-dessus ne fonctionnera pas dans Basic getopt
. GNU getopt
est installé par défaut sous Linux, mais sous Mac OS X et FreeBSD, il doit être installé séparément. Sous Mac OS X, installez MacPorts ( http://www.macports.org ) et ensuite faire sudo port install getopt
pour installer GNU getopt
(généralement en /opt/local/bin
), et assurez-vous que /opt/local/bin
se trouve dans le chemin du shell avant /usr/bin
. Sous FreeBSD, installez misc/getopt
.
Un guide rapide pour modifier le code d'exemple pour votre propre programme : Dans les premières lignes, tout est du "boilerplate" qui doit rester le même, sauf la ligne qui appelle getopt
. Vous devez changer le nom du programme après -n
spécifier les options courtes après -o
et des options longues après --long
. Mettez deux points après les options qui prennent une valeur.
Enfin, si vous voyez du code qui vient set
au lieu de eval set
il a été écrit pour BSD getopt
. Vous devez le modifier pour utiliser le eval set
qui fonctionne parfaitement avec les deux versions de getopt
tandis que la plaine set
ne fonctionne pas correctement avec GNU getopt
.
1 En fait, getopts
en ksh93
prend en charge les options aux noms longs, mais cet interpréteur de commandes n'est pas utilisé aussi souvent que le shell bash
. Sur zsh
utiliser zparseopts
pour obtenir cette fonctionnalité.
2 Techniquement, "GNU getopt
"Cette version a en fait été écrite pour Linux plutôt que pour le projet GNU. Cependant, elle suit toutes les conventions GNU, et le terme " GNU getopt
" est couramment utilisé (par exemple sous FreeBSD).
5 votes
À mon avis, la réponse acceptée n'est pas la meilleure. Elle ne montre pas comment utiliser getopts pour gérer les arguments "-" et "--", ce qui peut être fait, comme l'a démontré @Arvid Requate. J'insère une autre réponse qui utilise un concept similaire, mais qui traite également de l'erreur de l'utilisateur qui "oublie" d'insérer des valeurs pour les arguments qui sont nécessaires. Point clé : les getopts peuvent être utilisés. L'utilisateur doit éviter d'utiliser "getopt" à la place si la portabilité multiplateforme est nécessaire. De plus, getopts fait partie du standard POSIX pour les shells, il est donc probable qu'il soit portable.
0 votes
Duplicata possible de Comment analyser les arguments de la ligne de commande dans Bash ?