È perché nel primo caso, la shell corrente espande la variabile $ HELLO prima di eseguire i comandi. E non c'è una serie di variabili HELLO nella tua shell corrente.
env HELLO='Hello World' echo $HELLO
farà questo:
- espandono le variabili dato, in questo caso $ CIAO
- eseguire env con i 3 argomenti 'CIAO = Ciao Mondo', 'eco' e ' '(una stringa vuota, poiché non c'è una variabile HELLO impostata nella shell corrente)
- Il comando env verrà eseguito e verrà impostato HELLO =' Hello World 'nel suo ambiente
- env verrà eseguito echo con l'argomento '' (una stringa vuota)
Come si vede, la shell corrente ha espanso la variabile $ HELLO, che non è impostata.
HELLO='Hello World' bash -c 'echo $HELLO'
farà questo:
- impostare la variabile
HELLO='Hello World
per il seguente comando
- corsa bash con i 2 argomenti '-c' e 'echo $ CIAO'
- dal l'ultimo argomento è racchiuso tra virgolette singole, qualsiasi cosa al suo interno non è espansa
- la nuova bash a sua volta eseguirà il comando
echo $HELLO
- Per eseguire echo $ HELLO nella nuova sub-shell di bash, bash dapprima espande tutto ciò che può, $ HELLO in questo caso e la shell genitore imposta a "Hello World" per noi.
- Il subshell corre echo 'Ciao Mondo'
Se si è tentato di fare per esempio questo:
env HELLO='Hello World' echo '$HELLO'
- shell corrente sarebbe espandere nulla si può, che non è nulla in quanto $ CIAO è racchiuso tra virgolette singole
- eseguire env con i 3 argomenti 'CIAO = Ciao Mondo', ' echo' e '$ CIAO'
- il comando env verrà eseguito e impostare il CIAO = 'Ciao mondo' nel suo ambiente
- ENV verrà eseguito l'eco con l'argomento '$ CIAO'
In questo caso, non c'è nessuna shell che espanderà $ HELLO, quindi echo riceve la stringa $HELLO
e stampa quello. L'espansione variabile viene eseguita solo dalle shell.
Un controllo di integrità senza espansione è 'HELLO = 'Hello World' env | grep HELLO' che fa ciò che è richiesto ma è molto meno utile nella pratica della risposta accettata. –