Sprowadza się to do pytania, jak działa ewaluacja. Oba przykłady działają w ten sam sposób, problem występuje z powodu tego, jak powłoka (bash, tutaj) rozwija zmienne.
Kiedy napiszesz to polecenie:
HOME="foo" echo $HOME
$HOMERozpręża przed uruchomieniem polecenia . Dlatego jest on rozwijany do pierwotnej wartości, a nie nowej, dla której ustawiono ją dla polecenia. HOMEZmienna rzeczywiście została zmieniona w środowisku, że echokomenda jest uruchomiony w jednak jesteś drukowanie $HOMEod rodzica.
Aby to zilustrować, rozważ to:
$ HOME="foo" bash -c 'echo $HOME'
foo
$ echo $HOME
/home/terdon
Jak widać powyżej, pierwsze polecenie drukuje tymczasowo zmienioną wartość, HOMEa drugie drukuje oryginał, pokazując, że zmienna została zmieniona tylko tymczasowo. Ponieważ bash -c ...polecenie jest ujęte w pojedyncze cudzysłowy ( ' ') zamiast podwójnych ( " "), zmienna nie jest rozwijana i jest przekazywana w stanie niezmienionym do nowego procesu bash. Ten nowy proces następnie go rozwija i drukuje nową wartość, dla której został ustawiony. Możesz to zobaczyć, jeśli użyjesz set -x:
$ set -x
$ HOME="hello" echo "$HOME"
+ HOME=hello
+ echo hello
hello
Jak widać powyżej, zmienna $HOME nigdy nie jest przekazywana do echo. Widzi tylko swoją rozszerzoną wartość. Porównać z:
$ HOME="hello" bash -c 'echo $HOME'
+ HOME=hello
+ bash -c 'echo $HOME'
hello
Tutaj, ze względu na pojedyncze cudzysłowy, zmienna, a nie jej wartość, są przekazywane do nowego procesu.
local.