Est-il un moyen d'éviter les arguments de position en bash?
Je dois écrire une fonction dans bash. La fonction prendra environ 7 arguments. Je sais que je peux appeler une fonction comme ceci:
Pour appeler une fonction avec des paramètres:
function_name $arg1 $arg2
Et je peux utiliser mes paramètres à l'intérieur de la fonction:
function_name () {
echo "Parameter #1 is $1"
}
Ma question est, est-il une meilleure façon de consulter les paramètres à l'intérieur de la fonction? Puis-je éviter l'$1, $2, $3, .... chose et tout simplement utiliser le $arg1, $arg2, ...?
Est-il une bonne méthode pour cela ou dois-je besoin de ré-affecter ces paramètres à d'autres variables à l'intérieur de la fonction? E. g.:
function_name () {
$ARG1=$1
echo "Parameter #1 is $ARG1"
}
Un exemple serait très apprécié.
- Quelle est la différence entre l'utilisation de
$1
vs$ARG1
? - Je peux utiliser plus intuitive nom, au lieu de $1, $2. Les chiffres sont source de confusion.
- Avez-vous vraiment besoin de sept paramètres obligatoires? Une approche commune serait de tourner autant que possible dans les options, et de fournir une valeur par défaut lorsque cela a du sens. Il rend votre script beaucoup plus facile à utiliser si vous n'avez pas à mémoriser un particulier de position de commande pour un tel grand nombre d'arguments, même si la plupart des utilisateurs devraient remplacer les valeurs par défaut la plupart du temps.
- Hey @Bhushan! Je pense que j'ai une solution pour vous. J'ai posté une réponse: stackoverflow.com/questions/12128296/...
- Cette question ressemble à ceci : Spécifier des arguments de ligne de commande comme les paires nom=valeur de shell-script
Vous devez vous connecter pour publier un commentaire.
La façon la plus courante de le faire est d'attribuer les arguments des variables locales à la fonction, à savoir:
Une autre solution peut être getoptdes options de style de l'analyse.
Malheureusement, bash ne peut pas manipuler des options qui serait être plus lisible, c'est à dire:
Pour cela, vous devez soit utiliser l'externe
getopt
programme (qui je pense a de l'option de charge uniquement sur les systèmes GNU) ou de mettre en œuvre l'option de l'analyseur à la main, c'est à dire:Voir aussi: à l'aide de getopts en shell bash script pour obtenir de longue et de courte options de ligne de commande
Vous pouvez également être paresseux, et il suffit de passer la variable en tant qu'arguments à la fonction, à savoir:
et vous aurez
${from}
et${to}
dans la fonction comme des variables locales.Il suffit de noter que la même question que ci-dessous s'applique — si une variable n'est pas passé, il va être héritées du parent de l'environnement. Vous souhaiterez peut-être ajouter une "ligne de sécurité" comme:
pour s'assurer que
${from}
et${to}
sera désactiver lorsqu'il n'est pas passé.Et si quelque chose très mauvais est de votre intérêt, vous pouvez également affecter les arguments comme des variables globales lors de l'appel de la fonction, c'est à dire:
Ensuite, vous pouvez simplement utiliser
${from}
et${to}
dans lecopy()
fonction. Il suffit de noter, que vous devez ensuite toujours passer tous les paramètres. Sinon, une variable aléatoire peut s'infiltrer dans la fonction.Si vous avez bash 4.1 (je pense), vous pouvez également essayer d'utiliser des tableaux associatifs. Il vous permettra de passer des arguments nommés, mais il sera être moche. Quelque chose comme:
Puis dans
copy()
, vous auriez besoin de saisir le tableau.get_input()
, alors je vais utilisergi_prompt="blah blah blah"
, et dans la fonction,unset gi_prompt
. Par namespacing tout ce qui est lié à la fonction, ce qui empêche les fuites et les conflits de noms, tout en permettant une certaine souplesse.Vous pouvez toujours passer des choses par le biais de l'environnement:
Shell fonctions ont accès à toutes les variables disponibles dans leur contexte appelant, sauf pour ces noms de variables qui sont utilisées comme des variables locales à l'intérieur de la fonction elle-même. En outre, tous les non-locale de la variable définie dans une fonction est disponible à l'extérieur une fois que la fonction a été appelée. Considérons l'exemple suivant:
Cet extrait a la sortie suivante:
L'inconvénient de cette approche est que les fonctions qui ne sont pas autonomes et que la définition d'une variable en dehors d'une fonction peut avoir des effets secondaires imprévus. Il serait également rendre les choses plus difficiles si vous avez l'envie de transmettre des données à une fonction sans l'affecter à une variable d'abord, puisque cette fonction n'est pas à l'aide de paramètres positionnels plus.
La façon la plus commune pour résoudre ce problème est d'utiliser variables locales pour les arguments et toute variable temporaire dans une fonction:
Cela évite de polluer l'espace de noms environnement avec la fonction de variables locales.
Tout ce que vous avez à faire est de nom de variables sur la façon de l'appel de la fonction.
Ce n'est pas seulement une fonction de fonctions, vous pouvez avoir cette fonction dans son propre script et appel
a='hello world' test.sh
et cela fonctionne tout de mêmeComme un supplément peu de plaisir, vous pouvez combiner cette méthode avec des arguments de position (dire que vous avez été faire un script et que certains utilisateurs pourraient ne pas connaître les noms de variables).
Diable, pourquoi ne pas laisser les valeurs par défaut pour ces arguments trop? Bien sûr, facile comme bonjour!
Noter que si
test
était son propre script, vous n'avez pas besoin d'utiliser lelocal
mot-clé.Je pense que j'ai une solution pour vous.
Avec quelques astuces, vous pouvez passer des paramètres nommés à des fonctions, ainsi que des tableaux.
La méthode que j'ai développée permet d'accéder à des paramètres passés à une fonction comme ceci:
En d'autres termes, non seulement vous pouvez appeler vos paramètres par leurs noms (ce qui représente un plus lisible de base), vous pouvez passer des tableaux (et des références à des variables - cette fonction ne fonctionne qu'en bash 4.3 si)! De Plus, la cartographié les variables sont toutes dans le domaine local, tout comme $1 (et les autres).
Le code qui effectue ce travail est assez léger et fonctionne à la fois en bash 3 et bash 4 (ce sont les seules versions que j'ai testé avec). Si vous êtes intéressé par plus de trucs comme ça qui font de développement avec bash beaucoup plus agréable et plus facile, vous pouvez prendre un coup d'oeil à mon Bash Cadre De L'Infini, le code ci-dessous a été élaboré à cette fin.
Personnellement, j'ai été dans l'espoir de voir une sorte de syntaxe comme
Mais puisque ce n'est pas une chose, et je vois assez peu de références à des variables globales (pas sans la mise en garde de la portée et des conflits de nommage), je vais partager mon approche.
À l'aide de la
copy
fonction de Michal réponse:Ce qui est mauvais, parce que
from
etto
sont ces grandes paroles que n'importe quel nombre de fonctions peut utiliser ce fichier. Vous pourrait rapidement se retrouver avec un conflit de noms ou d'une "fuite" sur vos mains.Donc, mon approche est de "espace de noms" entre eux. J'ai le nom de la variable après la fonction et le supprimer une fois que la fonction est de faire avec elle. Bien sûr, je ne l'utilise que pour les valeurs facultatives qui ont des valeurs par défaut. Sinon, je viens de l'utiliser de position args.
Je voudrais faire un terrible boss...
Dans la pratique, mes noms de fonction sont plus élaborées que "copier" ou "lettre".
L'exemple le plus récent à ma mémoire est
get_input()
, qui agi_no_sort
etgi_prompt
.gi_no_sort
est une valeur vrai/faux qui détermine si l'achèvement des suggestions sont triés ou non. Par défaut à truegi_prompt
est une chaîne qui est...eh bien, c'est auto-explicatif. La valeur par défaut "".Les arguments de la fonction sont la source de ladite 'achèvement des suggestions" pour l'invite d'entrée, et comme l'a dit liste est tirée de
$@
dans la fonction, le "nommé args" sont facultatifs[1], et il n'y a pas de moyen évident de distinguer entre, d'une chaîne conçue comme un achèvement et un booléen/invite de message, ou vraiment n'importe quoi, séparés par des espaces dans bash, pour que la matière[2]; la solution ci-dessus fini par me sauver beaucoup de difficulté.notes:
Donc codé en dur
shift
et$1
,$2
, etc. sont hors de question.E. g. est
"0 Enter a command: {1..9} $(ls)"
une valeur de0
,"Enter a command:"
, et un ensemble de1 2 3 4 5 6 7 8 9 <directory contents>
? Ou sont"0"
,"Enter"
,"a"
, et"command:"
partie de ce jeu ainsi? Bash assumera le dernier si vous l'aimez ou pas.Arguments envoyés à des fonctions comme un n-uplet d'éléments, de sorte qu'ils n'ont pas de nom en tant que tel, juste des positions. cela permet quelques possibilités intéressantes comme ci-dessous, mais cela signifie que vous êtes coincé avec $1. $2, etc. quant à la carte pour mieux les noms, la question se résume à la taille de la fonction, et comment beaucoup plus clair il fera de la lecture du code. si son complexe, puis le mappage des noms significatifs ($BatchID, $Prenom, $SourceFilePath) est une bonne idée. pour des choses simples, mais cependant, il n'est probablement pas nécessaire. Je certianly ne serait pas la peine si vous utilisez des noms comme $arg1.
maintenant, si vous voulez juste de récupérer les paramètres, vous pouvez effectuer une itération sur eux:
juste un fait amusant; sauf si vous êtes du traitement d'une liste, vous êtes probablement intéressé à quelque chose de plus utile
c'est un vieux sujet, mais je tiens à partager la fonction ci-dessous (nécessite bash 4). Il analyse les arguments nommés et définit les variables dans les scripts de l'environnement. Assurez-vous simplement que vous avez sain d'esprit des valeurs par défaut pour tous les paramètres dont vous avez besoin. L'instruction d'exportation à la fin pourrait aussi être simplement un eval. Il est idéal en combinaison avec la touche shift pour étendre les scripts existants qui ont déjà quelques paramètres positionnels et vous ne voulez pas modifier la syntaxe, mais toujours ajouter un peu de souplesse.