¿Por qué --text = “$ @” solo pasa la primera palabra?

9

Cuando ejecuto el siguiente script con algunos argumentos como arg1 arg2 arg3:

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

Zenity crea un diálogo de entrada con este texto: "arg1", mientras que espero "arg1 arg2 arg3"

Si uso una variable como el siguiente script, muestra todos los argumentos para el texto de entrada.

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

¿Cuál es la diferencia entre estos scripts? ¿Por qué el primero reemplaza solo $@con el primer argumento?

Omid
fuente

Respuestas:

16

$@se expande para separar palabras (mientras que se $*expande a una sola palabra), como se explica en el bashmanual . Por lo tanto, cuando escribes

zenity --text="$@"

se expande a

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

Sin embargo, las asignaciones de variables de shell no sufren división de palabras. Tenga en cuenta que la división de campo / palabra se omite en la lista de expansiones para asignaciones variables en el bashmanual . Este comportamiento es consistente con la especificación POSIX . Entonces, cuando escribes

text="$@"

la variable textobtiene todos los parámetros posicionales como una sola palabra, equivalente a si hubiera escrito text="$*". De hecho, esta es la razón por la cual las comillas dobles a menudo son innecesarias en las asignaciones variables. Ambos

text=$@

y

text=$*

son perfectamente seguros

Entonces,

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

se expande "$text"a una sola palabra, razón por la cual esto funciona. Tenga en cuenta que --option="$@"es solo un argumento normal para el comando zenity, y no una asignación de variable de shell, por lo que la división de palabras tiene lugar aquí pero no en text=$@.

jw013
fuente
1
+1. Esto también funcionará: zenity --text="$*"- se "$*"expande a una sola palabra.
Glenn Jackman
+1 por enseñarme una cosa: man! = Documentación. Debería haber buscado info bash, también contiene la sección del manual a la que se ha vinculado.
manatwork
7

$@ se expande cada parámetro en una palabra separada, convirtiéndose

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

Use en su $*lugar para expandirlo en una sola palabra

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

que se convertirá

zenity --entry --text="arg1 arg2 arg3" # syntactically correct for zenity
hombre trabajando
fuente
Por favor, aclare por qué la variante $ text de la pregunta del OP funciona como se esperaba
iruvar
@ChandraRavoori, me atrapaste con eso. De acuerdo con el manual "No se realiza la división de palabras, con la excepción de" $ @ "" y "Si la expansión entre comillas dobles ocurre dentro de una palabra, la expansión del primer parámetro se une con la parte inicial de la palabra original, y la expansión del último parámetro se une con la última parte de la palabra original ", por lo que esperaría text="$@"expandirme text="arg1" "arg2" "arg3", lo que debería fallar. Pero ciertamente no es el caso.
manatwork
@ChandraRavoori La razón es que la división de campos no ocurre en asignaciones variables. Explico con más detalle en mi respuesta .
jw013
@ jw013: Pero de acuerdo con la referencia Bash Manual , "$@" hace someterse a la división de palabras, incluso en las asignaciones de variables.
ruakh
@ruakh El manual de bash no dice eso hasta donde yo sé. ¿Tienes una cita?
jw013