Pourquoi --text = “$ @” ne passe-t-il que le premier mot?

9

Lorsque j'exécute le script suivant avec quelques arguments comme arg1 arg2 arg3:

#!/bin/bash
zenity --entry --text="$@"

zenity crée une boîte de dialogue d'entrée avec ce texte: "arg1" alors que j'attends "arg1 arg2 arg3"

Si j'utilise une variable comme le script suivant, elle affiche tous les arguments pour le texte d'entrée.

#!/bin/bash
text="$@"
zenity --entry --text="$text"

Quelle est la différence entre ces scripts? Pourquoi le premier remplace- $@t-il uniquement par le premier argument?

Omid
la source

Réponses:

16

$@se développe en mots séparés (alors qu'il se $*développe en un seul mot), comme expliqué dans le bashmanuel . Ainsi, lorsque vous écrivez

zenity --text="$@"

il se développe pour

zenity --text="$1" "$2" "$3"

Cependant, les affectations de variables shell ne subissent pas de division de mots. Notez que le fractionnement champ / mot est omis dans la liste des extensions pour les affectations de variables dans le bashmanuel . Ce comportement est conforme à la spécification POSIX . Donc, quand vous écrivez

text="$@"

la variable textobtient tous les paramètres positionnels en un seul mot, équivalent à si vous aviez écrit text="$*". En effet, c'est la raison pour laquelle les guillemets doubles sont souvent inutiles dans les affectations de variables. Tous les deux

text=$@

et

text=$*

sont parfaitement sûrs.

Donc,

text=$@
zenity --option="$text"

se développe "$text"en un seul mot, c'est pourquoi cela fonctionne. Notez que le --option="$@"est juste un argument normal à la commande zenity, et non une affectation de variable shell, c'est pourquoi le fractionnement de mots a lieu ici mais pas dans text=$@.

jw013
la source
1
+1. Cela fonctionnera également: zenity --text="$*"- se "$*"développe en un seul mot.
glenn jackman
+1 pour m'avoir appris une chose: man! = Documentation. J'aurais dû rechercher info bash, il contient également la section du manuel à laquelle vous avez lié.
manatwork
7

$@ obtenir développé chaque paramètre dans un mot distinct, devenant

zenity --entry --text="arg1" "arg2" "arg3" # syntactically wrong for zenity

Utilisez-le à la $*place pour le développer en un seul mot

zenity --entry --text="$*"

qui deviendra

zenity --entry --text="arg1 arg2 arg3" # syntactically correct for zenity
homme au travail
la source
Veuillez expliquer pourquoi la variante $ text de la question du PO fonctionne comme prévu
iruvar
@ChandraRavoori, vous m'avez surpris avec ça. Selon le manuel "Le fractionnement des mots n'est pas effectué, à l'exception de" $ @ "" et "Si l'expansion entre guillemets se produit dans un mot, l'expansion du premier paramètre est jointe à 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. », donc je m'attendrais text="$@"à être étendu à text="arg1" "arg2" "arg3", ce qui devrait échouer. Mais ce n'est certainement pas le cas.
manatwork
@ChandraRavoori La raison est que le fractionnement des champs ne se produit pas dans les affectations de variables. J'explique plus en détail dans ma réponse .
jw013
@ jw013: Mais selon le Manuel de référence Bash , "$@" fait l' objet de césure de mots, même dans les affectations de variables.
ruakh
@ruakh Le manuel bash ne dit pas cela pour autant que je sache. Avez-vous un devis?
jw013