Por que --text = "$ @" passa apenas a primeira palavra?

9

Quando executo o seguinte script com alguns argumentos como arg1 arg2 arg3:

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

O zenity cria uma caixa de diálogo de entrada com este texto: "arg1", enquanto espero "arg1 arg2 arg3"

Se eu usar uma variável como o script a seguir, ela mostra todos os argumentos para o texto da entrada.

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

Qual a diferença entre esses scripts? Por que o primeiro substitui $@apenas pelo primeiro argumento?

Omid
fonte

Respostas:

16

$@expande para separar palavras (enquanto $*expande para uma única palavra), conforme explicado no bashmanual . Assim, quando você escreve

zenity --text="$@"

expande para

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

No entanto, as atribuições de variáveis ​​de shell não sofrem divisão de palavras. Observe que a divisão de campo / palavra é omitida na lista de expansões para atribuições de variáveis ​​no bashmanual . Esse comportamento é consistente com a especificação POSIX . Então, quando você escreve

text="$@"

a variável textobtém todos os parâmetros posicionais como uma única palavra, equivalente a se você tivesse escrito text="$*". De fato, essa é a razão pela qual aspas duplas geralmente são desnecessárias em atribuições de variáveis. Ambos

text=$@

e

text=$*

são perfeitamente seguros.

Assim,

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

expande "$text"para uma única palavra, e é por isso que isso funciona. Observe que este --option="$@"é apenas um argumento normal para o comando zenity, e não uma atribuição de variável do shell, e é por isso que a divisão de palavras ocorre aqui, mas não em text=$@.

jw013
fonte
11
+1. Isso também funcionará: zenity --text="$*"- "$*"expande para uma única palavra.
Glenn Jackman
+1 por me ensinar uma coisa: man! = Documentação. Eu deveria ter procurado informações bash, ele também contém a seção do manual que você vinculou.
manatwork
7

$@ expandido cada parâmetro em uma palavra separada, tornando-se

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

Use $*para expandi-lo em uma única palavra

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

que se tornará

zenity --entry --text="arg1 arg2 arg3" # syntactically correct for zenity
homem a trabalhar
fonte
Por favor, lançar luz sobre por que a variante $ texto da pergunta obras do OP como esperado
Iruvar
@ChandraRavoori, você me pegou com isso. De acordo com o manual “A divisão de palavras não é executada, com exceção de" $ @ "” e “Se a expansão de aspas duplas ocorrer em uma palavra, a expansão do primeiro parâmetro será associada à parte inicial da palavra original, e a expansão do último parâmetro é associada à última parte da palavra original. ”, então eu esperaria text="$@"ser expandido para text="arg1" "arg2" "arg3", o que deve falhar. Mas certamente não é o caso.
26512 manatwork
@ChandraRavoori O motivo é que a divisão de campos não acontece nas atribuições de variáveis. Eu explico com mais detalhes na minha resposta .
Jw013 26/10/12
@ jw013: Mas, de acordo com o Manual de Referência do Bash , a divisão de palavras "$@" é submetida, mesmo em atribuições de variáveis.
Ruakh 27/10
@ruakh O manual do bash não diz isso até onde eu sei. Você tem uma cotação?
Jw013 27/10/12