Dis, j'ai un script qui s'appelle avec cette ligne:
./myscript -vfd ./foo/bar/someFile -o /fizz/someOtherFile
ou celui-ci:
./myscript -v -f -d -o /fizz/someOtherFile ./foo/bar/someFile
Quelle est la façon acceptée de telle sorte que cette analyse dans chaque cas (ou une combinaison des deux) $v
, $f
et $d
seront tous mis à true
et $outFile
sera égal /fizz/someOtherFile
?
zparseopts -D -E -M -- d=debug -debug=d
Et avoir les deux-d
et--debug
dans le$debug
tableauecho $+debug[1]
retournera 0 ou 1 si l'un d'eux est utilisé. Ref: zsh.org/mla/users/2011/msg00350.htmlRéponses:
Méthode n ° 1: utiliser bash sans getopt [s]
Deux façons courantes de passer des arguments de paire clé-valeur sont:
Séparé par l'espace Bash (par exemple,
--option argument
) (sans getopt [s])Usage
demo-space-separated.sh -e conf -s /etc -l /usr/lib /etc/hosts
sortie du copier-coller du bloc ci-dessus:
Bash égal à séparé (par exemple,
--option=argument
) (sans getopt [s])Usage
demo-equals-separated.sh -e=conf -s=/etc -l=/usr/lib /etc/hosts
sortie du copier-coller du bloc ci-dessus:
Pour mieux comprendre,
${i#*=}
recherchez «Suppression de sous-chaîne» dans ce guide . Il est fonctionnellement équivalent à celui`sed 's/[^=]*=//' <<< "$i"`
qui appelle un sous-processus inutile ou`echo "$i" | sed 's/[^=]*=//'`
qui appelle deux sous-processus inutiles.Méthode n ° 2: utilisation de bash avec getopt [s]
à partir de: http://mywiki.wooledge.org/BashFAQ/035#getopts
Limitations de getopt (1) (anciennes
getopt
versions relativement récentes ):Les
getopt
versions plus récentes n'ont pas ces limitations.De plus, le shell POSIX (et autres) offre
getopts
qui n'a pas ces limitations. J'ai inclus un simplistegetopts
exemple .Usage
demo-getopts.sh -vf /etc/hosts foo bar
sortie du copier-coller du bloc ci-dessus:
Les avantages de
getopts
sont:dash
.-vf filename
dans la manière typique d'Unix, automatiquement.L'inconvénient
getopts
est qu'il ne peut gérer que des options courtes (-h
, pas--help
) sans code supplémentaire.Il y a un tutoriel getopts qui explique ce que signifient toutes les syntaxes et variables. En bash, il y en a aussi
help getopts
, qui pourrait être informatif.la source
getopt
qui inclut toutes les fonctionnalités degetopts
, puis certaines.man getopt
sur les sorties Ubuntu 13.04getopt - parse command options (enhanced)
comme nom, donc je suppose que cette version améliorée est standard maintenant.getopt
n'est pas un utilitaire GNU, il en fait partieutil-linux
.-gt 0
, supprimez votreshift
après leesac
, augmentez toutshift
de 1 et ajoutez ce cas:*) break;;
vous pouvez gérer des arguments non optionnels. Ex: pastebin.com/6DJ57HTc–default
. Dans le premier exemple, je remarque que si–default
est le dernier argument, il n'est pas traité (considéré comme non-opt), sauf s'ilwhile [[ $# -gt 1 ]]
est défini commewhile [[ $# -gt 0 ]]
Aucune réponse ne mentionne le getopt amélioré . Et la réponse la plus votée est trompeuse: elle ignore
-vfd
les options courtes de style (demandées par l'OP) ou les options après les arguments de position (également demandées par l'OP); et il ignore les erreurs d'analyse. Au lieu:getopt
de util-linux ou anciennement GNU glibc . 1getopt_long()
la fonction C de GNU glibc.getopt
ne peut pas le faire)script.sh -o outFile file1 file2 -v
(getopts
ne fait pas cela)=
les options longues de style:script.sh --outfile=fileOut --infile fileIn
(autoriser les deux est long si l'auto-analyse)-vfd
(travail réel si auto-analyse)-oOutfile
ou-vfdoOutfile
getopt --test
→ valeur de retour 4.getopt
ou intégrés au shellgetopts
sont d'une utilité limitée.Les appels suivants
tous reviennent
avec ce qui suit
myscript
1 getopt amélioré est disponible sur la plupart des «systèmes bash», y compris Cygwin; sur OS X, essayez brew install gnu-getopt ou
sudo port install getopt
2, les
exec()
conventionsPOSIXn'ont aucun moyen fiable de passer NULL binaire dans les arguments de la ligne de commande; ces octets mettent fin prématurément à l'argument3, première version publiée en 1997 ou avant (je ne l'ai suivi qu'en 1997)
la source
getopt
c'est la voie à suivre.getopt
est qu'il ne peut pas être utilisé de manière pratique dans les scripts wrapper où l'on peut avoir quelques options spécifiques au script wrapper, puis transmettre les options non-wrapper-script à l'exécutable encapsulé, intact. Disons que j'ai ungrep
wrapper appelémygrep
et que j'ai une option--foo
spécifique àmygrep
, alors je ne peux pas fairemygrep --foo -A 2
, et je-A 2
passe automatiquement àgrep
; Je dois fairemygrep --foo -- -A 2
. Voici mon implémentation au dessus de votre solution.man bash
Manière plus succincte
script.sh
Usage:
la source
while [[ "$#" > 1 ]]
si je veux soutenir la fin de la ligne avec un drapeau booléen./script.sh --debug dev --uglify fast --verbose
. Exemple: gist.github.com/hfossli/4368aa5a577742c3c9f9266ed214aa58./script.sh -d dev -d prod
entraîneraitdeploy == 'prod'
. Je l'ai quand même utilisé: P :): +1:./script.sh -d
ne générerait pas d'erreur mais serait simplement défini$deploy
sur une chaîne vide.de: digitalpeer.com avec des modifications mineures
Usage
myscript.sh -p=my_prefix -s=dirname -l=libname
Pour mieux comprendre,
${i#*=}
recherchez «Suppression de sous-chaîne» dans ce guide . Il est fonctionnellement équivalent à celui`sed 's/[^=]*=//' <<< "$i"`
qui appelle un sous-processus inutile ou`echo "$i" | sed 's/[^=]*=//'`
qui appelle deux sous-processus inutiles.la source
mount -t tempfs ...
. On peut probablement résoudre ce problème via quelque chose commewhile [ $# -ge 1 ]; do param=$1; shift; case $param in; -p) prefix=$1; shift;;
etc-vfd
les options courtes combinées de style.getopt()
/getopts()
est une bonne option. Volé d' ici :la source
$*
est une utilisation cassée degetopt
. (Il contient des arguments avec des espaces.) Voir ma réponse pour une utilisation correcte.Au risque d'ajouter un autre exemple à ignorer, voici mon schéma.
-n arg
et--name=arg
J'espère que c'est utile à quelqu'un.
la source
*) die "unrecognized argument: $1"
ou collecter les arguments dans une variable*) args+="$1"; shift 1;;
.shift 2
, émettantshift
deux fois au lieu deshift 2
. Suggéré la modification.J'ai environ 4 ans de retard sur cette question, mais je veux redonner. J'ai utilisé les réponses précédentes comme point de départ pour ranger mon ancienne analyse param param adhoc. J'ai ensuite refactorisé le code de modèle suivant. Il gère les paramètres longs et courts, en utilisant des arguments = ou séparés par des espaces, ainsi que plusieurs paramètres courts regroupés. Enfin, il réinsère tous les arguments non param dans les variables $ 1, $ 2 ... J'espère que c'est utile.
la source
-c1
. Et l'utilisation de=
pour séparer les options courtes de leurs arguments est inhabituelle ...J'ai trouvé le problème d'écrire une analyse portable dans des scripts si frustrant que j'ai écrit Argbash - un générateur de code FOSS qui peut générer le code d'analyse des arguments pour votre script et il a de belles fonctionnalités:
https://argbash.io
la source
Ma réponse est largement basée sur la réponse de Bruno Bronosky , mais j'ai en quelque sorte écrasé ses deux implémentations de bash pur en une que j'utilise assez fréquemment.
Cela vous permet d'avoir à la fois des options / valeurs séparées par des espaces et des valeurs définies égales.
Vous pouvez donc exécuter votre script en utilisant:
aussi bien que:
et les deux devraient avoir le même résultat final.
AVANTAGES:
Permet à la fois -arg = valeur et -arg valeur
Fonctionne avec n'importe quel nom d'argument que vous pouvez utiliser dans bash
Bash pur. Pas besoin d'apprendre / d'utiliser getopt ou getopts
LES INCONVÉNIENTS:
Impossible de combiner les arguments
Ce sont les seuls avantages / inconvénients auxquels je peux penser du haut de ma tête
la source
Je pense que celui-ci est assez simple à utiliser:
Exemple d'invocation:
la source
-a=1
comme style argc. Je préfère mettre d'abord les options principales -options et plus tard les options spéciales avec un seul espacement-o option
. Im à la recherche de la manière la plus simple vs meilleure de lire les arguments../myscript -v -d fail -o /fizz/someOtherFile -f ./foo/bar/someFile
avec votre propre script. L'option -d n'est pas définie comme d:Développant l'excellente réponse de @guneysus, voici un ajustement qui permet à l'utilisateur d'utiliser la syntaxe qu'il préfère, par exemple
contre
C'est-à-dire que les égaux peuvent être remplacés par des espaces.
Cette "interprétation floue" peut ne pas vous plaire, mais si vous créez des scripts interchangeables avec d'autres utilitaires (comme c'est le cas avec le mien, qui doit fonctionner avec ffmpeg), la flexibilité est utile.
la source
Cet exemple montre comment utiliser
getopt
eteval
etHEREDOC
etshift
pour gérer les paramètres courts et longs avec et sans une valeur requise qui suit. De plus, la déclaration switch / case est concise et facile à suivre.Les lignes les plus significatives du script ci-dessus sont les suivantes:
Court, précis, lisible et gère à peu près tout (à mon humble avis).
J'espère que cela aide quelqu'un.
la source
Je vous donne la fonction
parse_params
qui analysera les paramètres à partir de la ligne de commande.--all
égal à-all
égalall=all
)Le script ci-dessous est une démonstration de travail copier-coller. Voir la
show_use
fonction pour comprendre comment utiliserparse_params
.Limites:
-d 1
)--any-param
et-anyparam
sont équivalentseval $(parse_params "$@")
doit être utilisé dans la fonction bash (cela ne fonctionnera pas dans la portée globale)la source
show_use "$@"
EasyOptions ne nécessite aucune analyse:
la source
getopts fonctionne très bien si # 1 vous l'avez installé et # 2 vous avez l'intention de l'exécuter sur la même plate-forme. OSX et Linux (par exemple) se comportent différemment à cet égard.
Voici une solution (non getopts) qui prend en charge les indicateurs égaux, non égaux et booléens. Par exemple, vous pouvez exécuter votre script de cette manière:
la source
Voici comment je fais dans une fonction pour éviter de casser des getopts exécutés en même temps quelque part plus haut dans la pile:
la source
En développant la réponse de @ bruno-bronosky, j'ai ajouté un "préprocesseur" pour gérer une mise en forme courante:
--longopt=val
en--longopt val
-xyz
en-x -y -z
--
en charge pour indiquer la fin des drapeauxla source
Il existe plusieurs façons d'analyser les arguments cmdline (par exemple GNU getopt (non portable) vs BSD (OSX) getopt vs getopts) - tous problématiques. Cette solution est
=
séparateur-vxf
Exemples: tout
la source
Je voudrais proposer ma version d'analyse d'options, qui permet les opérations suivantes:
Permet également cela (peut être indésirable):
Vous devez décider avant utilisation si = doit être utilisé sur une option ou non. C'est pour garder le code propre (ish).
la source
Solution qui préserve les arguments non gérés. Démos incluses.
Voici ma solution. Il est TRÈS flexible et contrairement à d'autres, ne devrait pas nécessiter de packages externes et gère les arguments restants proprement.
L'utilisation est:
./myscript -flag flagvariable -otherflag flagvar2
Tout ce que vous avez à faire est de modifier la ligne des drapeaux valides. Il ajoute un tiret et recherche tous les arguments. Il définit ensuite l'argument suivant comme le nom du drapeau, par exemple
Le code principal (version courte, détaillée avec des exemples plus bas, également une version avec erreur):
La version détaillée avec des démos d'écho intégrées:
Un dernier, celui-ci commet une erreur si un argument non valide est transmis.
Avantages: Ce qu'il fait, il gère très bien. Il conserve les arguments inutilisés, contrairement à la plupart des autres solutions. Il permet également d'appeler des variables sans être définies manuellement dans le script. Il permet également de préremplir les variables si aucun argument correspondant n'est donné. (Voir l'exemple détaillé).
Inconvénients: impossible d'analyser une seule chaîne d'argument complexe, par exemple -xcvf serait traité comme un seul argument. Vous pouvez écrire un peu plus facilement du code supplémentaire dans le mien qui ajoute cette fonctionnalité.
la source
Je veux soumettre mon projet: https://github.com/flyingangel/argparser
Aussi simple que cela. L'environnement sera rempli de variables portant le même nom que les arguments
la source
Notez que
getopt(1)
c'était une courte erreur vivante d'AT & T.getopt a été créé en 1984 mais déjà enterré en 1986 car il n'était pas vraiment utilisable.
Une preuve du fait qui
getopt
est très dépassé est que lagetopt(1)
page de manuel mentionne toujours"$*"
au lieu de"$@"
, qui a été ajoutée au Bourne Shell en 1986 avec legetopts(1)
shell intégré afin de traiter les arguments avec des espaces à l'intérieur.BTW: si vous êtes intéressé par l'analyse des options longues dans les scripts shell, il peut être intéressant de savoir que l'
getopt(3)
implémentation de libc (Solaris) et lesksh93
deux ont ajouté une implémentation uniforme des options longues qui prend en charge les options longues comme alias pour les options courtes. Cela provoqueksh93
etBourne Shell
implémentation d'une interface uniforme pour les options longues viagetopts
.Un exemple d'options longues extraites de la page de manuel Bourne Shell:
getopts "f:(file)(input-file)o:(output-file)" OPTX "$@"
montre combien de temps les alias d'options peuvent être utilisés à la fois dans Bourne Shell et dans ksh93.
Voir la page de manuel d'un Bourne Shell récent:
http://schillix.sourceforge.net/man/man1/bosh.1.html
et la page de manuel pour getopt (3) d'OpenSolaris:
http://schillix.sourceforge.net/man/man3c/getopt.3c.html
et enfin, la page de manuel getopt (1) pour vérifier le $ * obsolète:
http://schillix.sourceforge.net/man/man1/getopt.1.html
la source
J'ai écrit un assistant bash pour écrire un bel outil bash
accueil du projet: https://gitlab.mbedsys.org/mbedsys/bashopts
exemple:
donnera de l'aide:
prendre plaisir :)
la source
Voici mon approche - en utilisant regexp.
-qwerty
-q -w -e
--qwerty
=
pour fournir des attributs, mais l'attribut correspond jusqu'à rencontrer un trait d'union + espace "délimiteur", donc il--q=qwe ty
qwe ty
y a un attribut-o a -op attr ibute --option=att ribu te --op-tion attribute --option att-ribute
est donc validescénario:
la source
Supposons que nous créons un script shell nommé
test_args.sh
comme suitAprès avoir exécuté la commande suivante:
La sortie serait:
la source
Utiliser les "arguments" du module à partir des modules bash
Exemple:
la source
Mélange d'arguments positionnels et basés sur des drapeaux
--param = arg (égal à délimité)
Mélanger librement les drapeaux entre les arguments positionnels:
peut être accompli avec une approche assez concise:
--param arg (espace délimité)
Il est généralement plus clair de ne pas mélanger
--flag=value
et--flag value
styles.C'est un peu risqué à lire, mais c'est toujours valable
La source
la source
Voici un getopts qui réalise l'analyse syntaxique avec un code minimal et vous permet de définir ce que vous souhaitez extraire dans un cas en utilisant eval avec une sous-chaîne.
Fondamentalement
eval "local key='val'"
Déclare les variables comme locales au lieu de globales comme la plupart des réponses ici.
Appelé comme:
$ {K: 3} est essentiellement une sous-chaîne pour supprimer la première
---
de la clé.la source
Cela peut également être utile de savoir, vous pouvez définir une valeur et si quelqu'un fournit une entrée, remplacez la valeur par défaut par cette valeur.
myscript.sh -f ./serverlist.txt ou simplement ./myscript.sh (et cela prend les valeurs par défaut)
la source
Une autre solution sans getopt [s], POSIX, ancien style Unix
Semblable à la solution que Bruno Bronosky a postée, celle-ci est sans utilisation
getopt(s)
.La principale caractéristique de différenciation de ma solution est qu'elle permet d'avoir des options concaténées ensemble comme
tar -xzf foo.tar.gz
est égal àtar -x -z -f foo.tar.gz
. Et comme danstar
,ps
etc., le trait d'union est facultatif pour un bloc d'options courtes (mais cela peut être changé facilement). Les options longues sont également prises en charge (mais lorsqu'un bloc commence par un puis deux tirets de tête sont requis).Code avec des exemples d'options
Pour l'exemple d'utilisation, veuillez consulter les exemples ci-dessous.
Position des options avec arguments
Pour ce que cela vaut, les options avec arguments ne sont pas les dernières (seules les options longues doivent l'être). Ainsi, par exemple dans
tar
(au moins dans certaines implémentations), lesf
options doivent être les dernières car le nom de fichier suit (tar xzf bar.tar.gz
fonctionne maistar xfz bar.tar.gz
ne fonctionne pas), ce n'est pas le cas ici (voir les exemples ultérieurs).Plusieurs options avec arguments
Comme autre bonus, les paramètres d'options sont consommés dans l'ordre des options par les paramètres avec les options requises. Regardez simplement la sortie de mon script ici avec la ligne de commande
abc X Y Z
(ou-abc X Y Z
):Options longues concaténées également
Vous pouvez également avoir des options longues dans le bloc d'options étant donné qu'elles se produisent en dernier dans le bloc. Les lignes de commande suivantes sont donc toutes équivalentes (y compris l'ordre dans lequel les options et ses arguments sont traités):
-cba Z Y X
cba Z Y X
-cb-aaa-0-args Z Y X
-c-bbb-1-args Z Y X -a
--ccc-2-args Z Y -ba X
c Z Y b X a
-c Z Y -b X -a
--ccc-2-args Z Y --bbb-1-args X --aaa-0-args
Tous ces éléments conduisent à:
Pas dans cette solution
Arguments facultatifs
Les options avec des arguments optionnels devraient être possibles avec un peu de travail, par exemple en regardant en avant s'il y a un bloc sans trait d'union; l'utilisateur aurait alors besoin de mettre un trait d'union devant chaque bloc suivant un bloc avec un paramètre ayant un paramètre optionnel. Peut-être que cela est trop compliqué pour communiquer à l'utilisateur, il vaut donc mieux avoir simplement un trait d'union dans ce cas.
Les choses deviennent encore plus compliquées avec plusieurs paramètres possibles. Je déconseille de faire des options en essayant d'être intelligent en déterminant si un argument pourrait être pour lui ou non (par exemple avec une option prend juste un nombre comme argument optionnel) car cela pourrait casser à l'avenir.
Personnellement, je préfère des options supplémentaires au lieu d'arguments facultatifs.
Arguments d'option introduits avec un signe égal
Tout comme avec les arguments facultatifs, je ne suis pas fan de cela (BTW, y a-t-il un fil pour discuter des avantages / inconvénients des différents styles de paramètres?) Mais si vous le souhaitez, vous pouvez probablement l'implémenter vous-même comme sur http: // mywiki.wooledge.org/BashFAQ/035#Manual_loop avec une
--long-with-arg=?*
déclaration de cas, puis en supprimant le signe égal (c'est BTW le site qui dit que la concaténation de paramètres est possible avec un certain effort mais "l'a laissé" comme exercice pour le lecteur) "ce qui m'a fait les croire sur parole mais je suis parti de zéro).Autres notes
Compatible POSIX, fonctionne même sur les anciennes configurations Busybox auxquelles j'ai dû faire face (par exemple
cut
,head
etgetopts
manquantes).la source