To dlatego, że w twoim pierwszym przypadku twoja obecna powłoka rozwija zmienną $ HELLO przed uruchomieniem poleceń. W twojej obecnej powłoce nie ma ustawionej zmiennej HELLO.
env HELLO='Hello World' echo $HELLO
będzie to zrobić:
- poszerzyć podane wszelkie zmienne, w tym przypadku $ CZEŚĆ
- wykonanie env z 3 argumenty 'hello = Hello World', 'Echo' i " "(pusty łańcuch, ponieważ w obecnej powłoce nie ma zmiennej HELLO)
- Komenda env uruchomi się i ustawi HELLO =" Hello World "w swoim środowisku
- env uruchomi się echo z argumentem '' (pusty ciąg)
Jak widać, bieżąca powłoka rozszerzyła zmienną $ HELLO, która nie jest ustawiona.
HELLO='Hello World' bash -c 'echo $HELLO'
zrobi to:
- ustawić zmienną
HELLO='Hello World
za pomocą następującego polecenia
- prowadzony bash z 2 argumenty '-c' i 'echo $ Hello'
- od ostatni argument jest ujęty w pojedyncze cudzysłowy, nic w nim nie jest rozwinięte
- nowy bash z kolei uruchomi polecenie
echo $HELLO
- Aby uruchomić echo $ HELLO w nowej pod-powłoce bash, bash najpierw rozszerza wszystko, co może, w tym przypadku $ HELLO, a powłoka rodzica ustawi to dla "Hello World" dla nas.
- podpowłoki działa echo 'Hello World'
Jeśli próbowali zrobić np to:
env HELLO='Hello World' echo '$HELLO'
- Obecny shell rozwinie wszystko, co możliwe, co nie jest niczym od $ CZEŚĆ jest ujęty w apostrofy
- prowadzony env z 3 argumenty 'hello = Hello World', " echo”i '$ Hello'
- polecenie env zostanie uruchomiony i ustawić Hello = 'Hello World' w swoim środowisku
- env potrwa echo z argumentem '$ Hello'
W tym przypadku nie ma powłoki, która rozszerzy $ HELLO, więc echo odbiera ciąg znaków $HELLO
i wypisuje go. Zmienne rozszerzanie jest wykonywane tylko przez powłoki.
Kontrola poprawności bez rozszerzenia: "HELLO =" Hello World "env | grep HELLO', który robi to, o co prosi, ale jest o wiele mniej przydatny w praktyce niż zaakceptowana odpowiedź. –