2012-12-21 10 views
21

Próbuję wywołać polecenie powłoki ze zmodyfikowanym środowiskiem za pomocą polecenia env.Ustawianie zmiennej środowiskowej dla jednego wywołania programu w bashu przy użyciu env

zgodnie z instrukcją

env HELLO='Hello World' echo $HELLO 

powinien echo Hello World, ale tak nie jest. Jeśli robię

HELLO='Hello World' bash -c 'echo $HELLO' 

drukuje Hello World jak oczekiwano (dzięki this answer tej informacji).

Czego mi tu brakuje?

Cheers, Niklas

+0

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ź. –

Odpowiedz

37

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.

4

myślę, co się dzieje, jest podobna do this situation w których byłem też zaskoczony.

W dużym skrócie zmienna ekspansja w pierwszym przypadku jest wykonywana przez bieżącą powłokę, która w swoim środowisku nie ma wartości $HELLO. W drugim przypadku pojedyncze cudzysłowy uniemożliwiają jednak wykonanie bieżącej powłoki, więc wszystko działa zgodnie z oczekiwaniami.

Uwaga jak zmienia apostrofów aby cudzysłowach Zapobiega to polecenie działa tak, jak chcesz:

HELLO='Hello World' bash -c "echo $HELLO" 

Teraz zostanie to w przypadku braku tego samego powodu co pierwsze komendy w swoim pytaniu.

+0

Prawidłowo. W pierwszym przypadku jest to bieżąca powłoka, która rozwija zmienną. W drugim przypadku wykonywany jest nowy "bash", który jest wykonywany. –

+0

Również tutaj wielkie dzięki za szybką odpowiedź! Niestety, mogę tylko udzielić jednej odpowiedzi miłego, zielonego kleszcza – Niklas

2

To działa i jest dobre dla mnie

$ MY_VAR='Hello' ANOTHER_VAR='World!!!' && echo "$MY_VAR $ANOTHER_VAR" 
Hello World!!! 
+1

Nie sądzę, że ma to związek z częścią "dla jednego programu". Vary tutaj pozostaną ustawione dla bieżącej sesji, więc będziesz mógł kontynuować ich echo. –

0

Tutaj jest łatwiejszy sposób, aby potwierdzić powłokę działa zgodnie z oczekiwaniami.

env A=42 env 
env 

pierwszych serii poleceń określa A do 42 i biegnie env. Drugie polecenie uruchamia również przebiegi env. Porównaj wyniki obu.

Powiązane problemy