J'écris un script très simple qui appelle un autre script, et je dois propager les paramètres de mon script actuel au script que j'exécute.
Par exemple, mon nom de script est foo.sh
et appellebar.sh
foo.sh:
bar $1 $2 $3 $4
Comment puis-je faire cela sans spécifier explicitement chaque paramètre?
bash
command-line-arguments
Fragsworth
la source
la source
Réponses:
Utilisez
"$@"
plutôt que plain$@
si vous souhaitez que vos paramètres soient transmis de la même manière.Observer:
la source
'arg with spaces'
pour les trois exemples. J'ai été surpris par les résultats; j'espère que vous pourrez les expliquer../foo.sh "arg with spaces"
et./foo.sh 'arg with spaces'
sont 100% identiques, donc je ne vois pas comment la suggestion de l'ajouter aux exemples donnés serait d'une quelconque utilité.Pour bash et autres obus de type Bourne:
la source
$argv:q
- être fonctionnera dans certaines variantes de csh.exec java com.myserver.Program "$@"
Cela provoque l'exécution de bash en java, plutôt que d'attendre qu'il se termine. Vous utilisez donc un emplacement de processus en moins. De plus, si le processus parent (qui a exécuté votre script) le regarde via le pid et s'attend à ce que ce soit le processus 'java', certaines choses inhabituelles pourraient se casser si vous ne faites pas d'exec; l'exec fait java hériter du même pid.args=("$@")
et développez chaque élément en tant que «mot» shell séparé ( semblable à"$@"
) avec"${args[@]}"
."$@"
, comme cela échouera si vous avez échappé des espaces dans un argument, ou des caractères nuls, ou d'autres caractères spéciaux?Utilisation
"$@"
(fonctionne pour tous les compatibles POSIX ).De Bash par exemple .
la source
$*
. Je crois qu'il y a une progression historique ici;$*
ne fonctionnait pas comme prévu, a donc$@
été inventé pour le remplacer; mais les règles de citation étant ce qu'elles sont, les doubles guillemets qui l'entourent sont toujours requis (ou cela reviendra à la$*
sémantique brisée ).echo "$@"
as,./script.sh a "b c" d
vous obtenez simplementa b c d
au lieu dea "b c" d
, ce qui est très différent.echo
reçoit trois arguments:"a" "b c" "d"
(puis le shell les joint ensemble dans le cadre de son expansion de chaîne). Mais si vous aviez utilisé,for i in "$@"; do echo $i; done
vous auriez obtenua⏎b c⏎d
.Je sais que cela a été bien répondu, mais voici une comparaison entre "$ @" $ @ "$ *" et $ *
Contenu du script de test:
Maintenant, exécutez le script de test avec divers arguments:
la source
Je pensais que cela pourrait être un peu plus utile lorsque vous essayez de tester comment les arguments entrent dans votre script
la source
$#
""
,''
comme argument, même s'il n'y a pas d'arguments, il est silencieux. J'ai essayé de résoudre ce problème, mais j'ai besoin d'une boucle for et d'un compteur avec$#
. Je viens d'ajouter ceci à la fin:echo "End of args or received quoted null"
Mon SUN Unix a beaucoup de limitations, même "$ @" n'a pas été interprété comme souhaité. Ma solution de contournement est $ {@}. Par exemple,
Soit dit en passant, je devais avoir ce script particulier parce que mon Unix ne supporte pas non plus grep -r
la source
ksh
Si vous incluez
$@
dans une chaîne entre guillemets d'autres caractères, le comportement est très étrange lorsqu'il y a plusieurs arguments, seul le premier argument est inclus à l'intérieur des guillemets.Exemple:
Rendements:
Mais affectons d'abord à une variable différente:
Rendements:
la source
"$@"
in bash. Cela permet également d'illustrer la principale différence entre$@
et$*
et pourquoi ils sont tous les deux utiles. À partir de labash(1)
page de manuel de la section Paramètres spéciaux: "*
- Lorsque l'expansion se produit entre guillemets, elle se développe en un seul mot avec la valeur de chaque paramètre […] Autrement dit,"$*"
est équivalent à"$1c$2c..."
, oùc
est [$IFS
]." Et en effet, utiliser à la$*
place de$@
dans votre premier exemple aurait généré une sortie identique à la deuxième version."$@"
. Toujours à partir de la page de manuel: "@
- Lorsque l'expansion se produit entre guillemets doubles, chaque paramètre se développe en un mot distinct. C'est-à-dire,"$@"
est équivalent à"$1"
"$2"
... Si l'expansion entre guillemets se produit dans un mot, l'expansion du premier paramètre est jointe avec la partie de début du mot d'origine, et l'expansion du dernier paramètre est jointe à la dernière partie du mot d'origine. " ... Et en effet, si votre code avait étébash -c "true foo $@ bar baz"
, alors exécutez-le comme letest.sh one two
ferait netbash -c 'true foo one' 'two bar baz'
.$*
, je semble oublier qu'elle existe ..$@
je commençais à gagner du terrain lorsque j'ai commencé à écrire des scripts shell, je dois encore me rappeler qu'il est là. Il était courant de les voir"$*"
utilisés dans des scripts ... alors l'auteur se rendrait compte qu'il brisait tous leurs arguments ensemble, alors ils essayaient toutes sortes de bêtises complexes avec le fractionnement de mots"$*"
, ou [ré] assemblaient une liste d'arguments en boucle plusshift
pour les tirer un par un ... juste en utilisant$@
résout le problème. (Aide que bash utilise également le même mnémonique pour accéder aux membres du tableau:${var[*]}
pour tous en tant que mot,${var[@]}
pour une liste de mots.)bash -c
d'une manière qui n'a absolument aucun sens.Parfois, vous voulez passer tous vos arguments, mais précédé d'un indicateur (par exemple
--flag
)Vous pouvez le faire de la manière suivante:
Remarque: pour éviter la division de champs supplémentaires, vous devez citer
%s
et$@
, et pour éviter d'avoir une seule chaîne, vous ne pouvez pas citer le sous-shell deprintf
.la source
Fonctionne bien, sauf si vous avez des espaces ou des caractères d'échappement. Je ne trouve pas le moyen de capturer les arguments dans ce cas et de les envoyer à un ssh à l'intérieur du script.
Cela pourrait être utile mais si moche
la source
Beaucoup de réponses ici recommandent
$@
ou$*
avec et sans guillemets, mais aucune ne semble expliquer ce que cela fait vraiment et pourquoi vous devriez le faire. Alors laissez-moi voler cet excellent résumé de cette réponse :Notez que les guillemets font toute la différence et sans eux, les deux ont un comportement identique.
Dans mon but, j'avais besoin de passer les paramètres d'un script à un autre tels quels et pour cela la meilleure option est:
Ne remarquez aucun devis et
$@
devrait également fonctionner dans la situation ci-dessus.la source
bar "$@"
sera équivalent àbar "$1" "$2" "$3" "$4"
Notez que les guillemets sont importants!
"$@"
,$@
,"$*"
Ou$*
seront chacun se comportent légèrement différemment en ce qui concerne s'échapper et concaténation comme décrit dans cette réponse stackoverflow .Un cas d'utilisation étroitement lié passe tous les arguments donnés à l'intérieur d'un argument comme celui-ci:
bash -c "bar \"$1\" \"$2\" \"$3\" \"$4\""
.J'utilise une variante de la réponse de @ kvantour pour y parvenir:
bash -c "bar $(printf -- '"%s" ' "$@")"
la source