Jaka jest różnica między używaniem:
eval "echo "foo""
i
echo "echo "foo"" | bash
czy są jakieś?
Komentarze
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, alex=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.
( eval 'echo "foo"' )