Dlaczego --text = „$ @” przekazuje tylko pierwsze słowo?

9

Kiedy uruchamiam następujący skrypt z kilkoma argumentami, takimi jak arg1 arg2 arg3:

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

zenity tworzy okno dialogowe z tym tekstem: „arg1”, podczas gdy oczekuję „arg1 arg2 arg3”

Jeśli użyję zmiennej takiej jak poniższy skrypt, pokaże wszystkie argumenty dla tekstu wpisu.

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

Jaka jest różnica między tymi skryptami? Dlaczego pierwszy zastępuje $@się tylko pierwszym argumentem?

Omid
źródło

Odpowiedzi:

16

$@rozwija się do oddzielnych słów (podczas gdy $*rozwija się do jednego słowa), jak wyjaśniono w bashinstrukcji . Tak więc, kiedy piszesz

zenity --text="$@"

rozwija się do

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

Jednak przypisania zmiennych powłoki nie podlegają dzieleniu słów. Zauważ, że podział pola / słowa jest pominięty na liście rozszerzeń przypisań zmiennych w bashpodręczniku . To zachowanie jest zgodne ze specyfikacją POSIX . Więc kiedy piszesz

text="$@"

zmienna textpobiera wszystkie parametry pozycyjne jako pojedyncze słowo, równoważne z tym, co napisałeś text="$*". Rzeczywiście, jest to powód, dla którego podwójne cudzysłowy są często niepotrzebne przy przypisywaniu zmiennych. Obie

text=$@

i

text=$*

są całkowicie bezpieczne.

Więc,

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

rozwija się "$text"do pojedynczego słowa, dlatego to działa. Zauważ, że --option="$@"jest to zwykły argument polecenia zenity, a nie przypisanie zmiennej powłoki, dlatego dzielenie słów odbywa się tutaj, ale nie w text=$@.

jw013
źródło
1
+1. Działa to również: zenity --text="$*"- "$*"rozwija się do jednego słowa.
glenn jackman
+1 za nauczenie mnie jednej rzeczy: człowiek! = Dokumentacja. Powinienem był przeszukać info bash, zawiera on także sekcję manualną, do której linkujesz.
manatwork
7

$@ zostań rozwinięty każdy parametr osobnym słowem, stając się

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

Użyj $*zamiast tego, aby rozwinąć go o jedno słowo

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

który się stanie

zenity --entry --text="arg1 arg2 arg3" # syntactically correct for zenity
człowiek w pracy
źródło
Wyjaśnij,
@ChandraRavoori, przyłapałeś mnie na tym. Zgodnie z instrukcją „Dzielenie słów nie jest wykonywane, z wyjątkiem„ $ @ ”” i „Jeśli podwójne wyrażenie występuje w jednym słowie, rozwinięcie pierwszego parametru jest łączone z początkową częścią oryginalnego słowa, a rozwinięcie ostatniego parametru jest połączone z ostatnią częścią oryginalnego słowa. ”, więc spodziewałbym text="$@"się rozwinięcia do text="arg1" "arg2" "arg3", co powinno się nie powieść. Ale na pewno tak nie jest.
manatwork
@ChandraRavoori Powodem jest to, że dzielenie pól nie występuje w przypisaniach zmiennych. Wyjaśniam bardziej szczegółowo w mojej odpowiedzi .
jw013,
@ jw013: Ale według Bash Reference Manual , "$@" nie ulegają rozszczepieniu słowo, nawet w zmiennych zadań.
ruakh
@ruakh Podręcznik bash nie mówi tego o ile wiem. Czy masz wycenę?
jw013