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?
shell
environment-variables
echo
ashleysmithgpu
źródło
źródło
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
to będzie działać.
export
sprawi, że zmienna pojawi się w środowisku później wykonywanych poleceń (zobacz, jak to działa w bash, patrzhelp export
). Jeśli potrzebujesz, aby zmienna pojawiła się tylko w środowisku jednego polecenia, użyj tego, co próbowałeś, tj .:źródło
$TEST
przed wykonaniem wiersza poleceń. Poecho
uruchomieniu (zwróć też uwagę, żeecho
zwykle tłumaczy się na wbudowane polecenie powłoki, a nie/bin/echo
), widzi zmienną ustawioną w swoim środowisku. Jednakecho $TEST
nie każeecho
wypisywać zawartości zmiennejTEST
ze swojego środowiska. Mówi powłoce, aby działałaecho
z argumentem będącym tym, co aktualnie znajduje się w zmiennej o nazwieTEST
- 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 dosh -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
Przekazujesz
var=value
ciąg znaków do środowiska, które odbiera echo. Jednakecho
nic nie robi z listą środowiska, a zresztą w większości powłokecho
jest wbudowany i dlatego nie jest wykonywany .Jeśli napisałeś
To byłaby inna sprawa. Przechodzimy tutaj
var=value
dosh
polecenia ish
zdarza się, że korzystamy z jego środowiska. Powłoki konwertują każdą zmienną otrzymaną ze swojego środowiska na zmienną powłokową, więc otrzymywanavar
zmienna środowiskowash
zostanie przekonwertowana na$var
zmienną, a kiedy rozwinie ją w tymecho
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 znowuecho
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):
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”:
Zsh umożliwia korzystanie z funkcji wbudowanych:
lub:
W przypadku bash i zsh (ale nie ash, pdksh lub AT&T ksh) ta sztuczka działa również:
Wariant, który działa w kilku więcej skorup (
dash
,mksh
,yash
) ale niezsh
(chyba, że wsh
/ksh
emulacji):(użycie
command
przed specjalnym wbudowanym (tutajeval
) w powłokach POSIX usuwa ich specjalność (tutaj, przypisania zmiennych z nich obowiązują po ich powrocie))źródło
Robisz to poprawnie, ale składnia bash jest łatwa do błędnej interpretacji: możesz pomyśleć, że
echo $TEST
powodujeecho
to pobranieTEST
env var, a następnie wydrukowanie go, nie robi tego. Tak podanenastępnie
obejmuje następującą sekwencję:
Powłoka analizuje cały wiersz poleceń i wykonuje wszystkie podstawienia zmiennych, więc wiersz poleceń staje się
Tworzy zmienne temp ustawione przed poleceniem, więc zapisuje bieżącą wartość
TEST
i zastępuje ją wartością 456; linia komend jest terazWykonuje 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:
źródło
printenv
pomocny w testowaniu / weryfikacji koncepcji (zachowuje się jak skrypt, w przeciwieństwie doecho
)Możesz zacząć działać, używając:
źródło
TEST=foo
działa jako osobna instrukcja - nie jest ona ustawiona tylko w kontekścieecho
.