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
lastpipejest 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
bashmożna wykonać w górna powłoka w zależności od opcji, alex=42z 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
bashwykona 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"' )