Jeśli ucieknę
export TEST=foo
echo $TEST
Wyprowadza foo.
Jeśli ucieknę
TEST=foo echo $TEST
To nie. Jak mogę uzyskać tę funkcjonalność bez użycia eksportu lub skryptu?
Jeśli ucieknę
export TEST=foo
echo $TEST
Wyprowadza foo.
Jeśli ucieknę
TEST=foo echo $TEST
To nie. Jak mogę uzyskać tę funkcjonalność bez użycia eksportu lub skryptu?
Odpowiedzi:
Wynika to z faktu, że powłoka rozwija zmienną w wierszu poleceń, zanim faktycznie uruchomi polecenie, i wówczas zmienna nie istnieje. Jeśli użyjesz
TEST=foo; echo $TEST
to będzie działać.
export
sprawi, że zmienna pojawi się w środowisku później wykonywanych poleceń (zobacz, jak to działa w bash, patrz help export
). Jeśli potrzebujesz, aby zmienna pojawiła się tylko w środowisku jednego polecenia, użyj tego, co próbowałeś, tj .:
TEST=foo your-application
$TEST
przed wykonaniem wiersza poleceń. Po echo
uruchomieniu (zwróć też uwagę, że echo
zwykle tłumaczy się na wbudowane polecenie powłoki, a nie /bin/echo
), widzi zmienną ustawioną w swoim środowisku. Jednak echo $TEST
nie każe echo
wypisywać zawartości zmiennej TEST
ze swojego środowiska. Mówi powłoce, aby działała echo
z argumentem będącym tym, co aktualnie znajduje się w zmiennej o nazwie TEST
- i są to dwie bardzo różne rzeczy.
var=value sh -c 'echo "$var"'
?
"… $var …"
), Ale nie w pojedynczych cudzysłowach (np '… $var …'
.). Ponieważ echo "$var"
znajduje się w pojedynczych cudzysłowach, cały ciąg znaków jest przekazywany do sh -c
powłoki new ( ) bez interpretacji przez zewnętrzną, interaktywną powłokę. … (Ciąg dalszy)
sh -c
) powłokę potomną.
Podejrzewam, że chcesz mieć zmienne powłoki , które mają ograniczony zasięg, a nie zmienne środowiskowe. Zmienne środowiskowe to lista ciągów znaków przekazywanych do poleceń podczas ich wykonywania .
W
var=value echo whatever
Przekazujesz var=value
ciąg znaków do środowiska, które odbiera echo. Jednak echo
nic nie robi z listą środowiska, a zresztą w większości powłok echo
jest wbudowany i dlatego nie jest wykonywany .
Jeśli napisałeś
var=value sh -c 'echo "$var"'
To byłaby inna sprawa. Przechodzimy tutaj var=value
do sh
polecenia i sh
zdarza się, że korzystamy z jego środowiska. Powłoki konwertują każdą zmienną otrzymaną ze swojego środowiska na zmienną powłokową, więc otrzymywana var
zmienna środowiskowa sh
zostanie przekonwertowana na $var
zmienną, a kiedy rozwinie ją w tym echo
wierszu poleceń, stanie się echo value
. Ponieważ środowisko jest domyślnie dziedziczone, echo
otrzyma również var=value
w swoim środowisku (lub zrobiłby, gdyby zostało wykonane), ale znowu echo
nie dba o środowisko.
Teraz, jeśli podejrzewam, że chcesz ograniczyć zakres zmiennych powłoki, istnieje kilka możliwych podejść.
Przenośny (Bourne i POSIX):
(var=value; echo "1: $var"); echo "2: $var"
Powyższe (...) uruchamia podpowłokę (nowy proces powłoki w większości powłok), więc każda zadeklarowana tam zmienna wpłynie tylko na tę podpowłokę, więc spodziewam się, że powyższy kod wyświetli „1: wartość” oraz „2:” lub „2: cokolwiek-var-was-set-to-before”.
W większości powłok podobnych do Bourne'a możesz używać funkcji i wbudowanego „lokalnego”:
f() {
local var
var=value
echo "1: $var"
}
f
echo "2: $var"
Zsh umożliwia korzystanie z funkcji wbudowanych:
(){ local var=value; echo "1: $var"; }; echo "2: $var"
lub:
function { local var=value; echo "1: $var"; }; echo "2: $var"
W przypadku bash i zsh (ale nie ash, pdksh lub AT&T ksh) ta sztuczka działa również:
var=value eval 'echo "1: $var"'; echo "2: $var"
Wariant, który działa w kilku więcej skorup ( dash
, mksh
, yash
) ale nie zsh
(chyba, że w sh
/ ksh
emulacji):
var=value command eval 'echo "1: $var"'; echo "2: $var"
(użycie command
przed specjalnym wbudowanym (tutaj eval
) w powłokach POSIX usuwa ich specjalność (tutaj, przypisania zmiennych z nich obowiązują po ich powrocie))
Robisz to poprawnie, ale składnia bash jest łatwa do błędnej interpretacji: możesz pomyśleć, że echo $TEST
powoduje echo
to pobranie TEST
env var, a następnie wydrukowanie go, nie robi tego. Tak podane
export TEST=123
następnie
TEST=456 echo $TEST
obejmuje następującą sekwencję:
Powłoka analizuje cały wiersz poleceń i wykonuje wszystkie podstawienia zmiennych, więc wiersz poleceń staje się
TEST=456 echo 123
Tworzy zmienne temp ustawione przed poleceniem, więc zapisuje bieżącą wartość TEST
i zastępuje ją wartością 456; linia komend jest teraz
echo 123
Wykonuje pozostałe polecenie, które w tym przypadku wypisuje 123 na standardowe wyjście (więc polecenie powłoki, które pozostaje, nawet nie używało wartości temp TEST
)
Przywraca wartość TEST
Zamiast tego użyj printenv, ponieważ nie wiąże się to z podstawieniem zmiennych:
>> export TEST=123
>> printenv TEST
123
>> TEST=456 printenv TEST
456
>> printenv TEST && TEST=456 printenv TEST && TEST=789 printenv TEST && printenv TEST
123
456
789
123
>>
printenv
pomocny w testowaniu / weryfikacji koncepcji (zachowuje się jak skrypt, w przeciwieństwie do echo
)
Możesz zacząć działać, używając:
TEST=foo && echo $TEST
TEST=foo
działa jako osobna instrukcja - nie jest ona ustawiona tylko w kontekście echo
.