eval a pipe through bash

Jaka jest różnica między używaniem:

eval "echo "foo"" 

i

echo "echo "foo"" | bash 

czy są jakieś?

Komentarze

  • Tutaj ' jest kolejna odmiana z nieco innym zachowaniem, jeśli chodzi o środowiska wykonawcze: ( eval 'echo "foo"' )

Odpowiedź

Krótka odpowiedź

Polecenie uruchamiane przez eval jest wykonywane w bieżącej powłoce, a polecenie przesyłane potokiem do bash jest wykonywane w podpowłoce, np .:

> echo "x=42" | bash; echo $x > eval "x=42"; echo $x 42 

Dłuższa odpowiedź

W komentarzach stwierdzono, że w nowszych wersjach bash (> = 4.2) pierwsze polecenie może również mieć ten sam efekt. Jednak wygląda na to, że tak nie jest.

W rzeczywistości jest kilka czynników, które powodują, że polecenie potokowe nie działa w bieżącej sesji: potok i bash polecenie.

W większości polecenia potokowe działają w podpowłokach. Instrukcja Bash ( Sekcja 3.2.2: Potoki ) zawiera następujące informacje:

Każde polecenie w potoku jest wykonywane we własnej podpowłoce (patrz Środowisko wykonywania poleceń ).

Jak wskazano w komentarzach, zachowanie to można zmodyfikować za pomocą opcji lastpipe. Podręcznik Bash ( Sekcja 4.3.2: Wbudowany Shopt ) zawiera następujące informacje na temat opcji lastpipe:

lastpipe

Jeśli jest ustawiona, a kontrola zadań nie jest aktywna, powłoka wykonuje ostatnie polecenie potoku niewykonanego w tło w bieżącym środowisku powłoki.

Możemy sprawdzić, czy tak jest w następujący sposób.

Najpierw włącz lastpipe:

> shopt -s lastpipe 

Następnie wyłącz kontrolę zadań:

> set +m 

Teraz wykonaj polecenie, które ustawia zmienną z potoku:

> unset x > echo x=42 | while IFS= read -r line; do eval "${line}"; done; > echo $x 42 

Zauważ, że używamy while loop i polecenie read jako obejście problemu, ponieważ polecenie eval nie może odczytać swoich danych wejściowych ze standardowego wejścia (stąd nie może pobrać danych wejściowych z a pipe).

Ten przykład pokazuje, że w rzeczywistości może to zrobić najbardziej prawe polecenie w potoku , należy wykonać w bieżącej powłoce. Jednak w rzeczywistości nie ma to wpływu na nasz oryginalny przykład. Nawet przy włączonym lastpipe i wyłączonej kontroli zadań nadal otrzymujemy następujący wynik podczas przesyłania do bash:

> echo "x=42" | bash; echo $x > 

Dzieje się tak, ponieważ polecenie bash samo wykonuje swoje dane wejściowe w podpowłoce.

Komentarze

  • to dobra obserwacja, czy nie ' nie zdawałem sobie z tego sprawy, ale tak myślę, że ' Jak działają potoki
  • Po prostu ciekawi, jaki jest powód, dla którego nie zaakceptowałeś odpowiedzi?
  • W przypadku basha 4.2+ podczas uruchamiania skryptu (a dokładniej, gdy kontrola zadań jest wyłączona) i shopt lastpipe jest ustawiony, a potok nie ma tła, ale biegnie prawy koniec potoku w ' na górze ' powłoka nie jest podpowłoką. Zobacz unix.stackexchange.com/questions/9954/… i unix.stackexchange.com/questions/136206/readarray-or-pipe-issue
  • @ dave_thompson_085 Polecenie bash można wykonać w górna powłoka w zależności od opcji, ale x=42 z pewnością będzie działać w czymś, co można rozsądnie nazwać podpowłoką.
  • @AlexanderMills Właściwie potok nie jest ' t jedyny problem. Polecenie bash wykona swoje dane wejściowe w podpowłoce, niezależnie od tego, czy w grę wchodzi potok, czy nie. Zobacz aktualizację mojego rozwiązania, aby uzyskać więcej informacji.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *