Care este diferența dintre utilizarea:
eval "echo "foo""
și
echo "echo "foo"" | bash
există vreunul?
Comentarii
Răspuns
Răspuns scurt
Comanda executată de eval
este executată în shell-ul curent și comanda canalizată către bash
este executată într-un sub-shell, de exemplu:
> echo "x=42" | bash; echo $x > eval "x=42"; echo $x 42
Răspuns mai lung
În comentarii s-a făcut afirmația că în versiunile mai recente ale bash
(> = 4.2) prima comandă ar putea avea, de asemenea, același efect. Cu toate acestea, acest lucru nu pare să fie cazul.
Există, de fapt, câțiva factori care determină ca comanda canalizată să nu ruleze în sesiunea curentă: conducta și bash
command.
În cea mai mare parte, comenzile canalizate rulează în sub-shell-uri. Manualul Bash ( Secțiunea 3.2.2: Conducte ) are următoarele informații:
Fiecare comandă dintr-o conductă este executată în propriul său subshell (consultați Mediul de executare a comenzilor ).
După cum sa subliniat în comentarii, acest comportament poate fi modificat prin opțiunea lastpipe
. Manualul Bash ( Secțiunea 4.3.2: The Shopt Builtin ) are următoarele informații despre opțiunea lastpipe
:
lastpipe
Dacă este setat și controlul lucrărilor nu este activ, shell rulează ultima comandă a unei conducte care nu a fost executată în fundal în mediul shell actual.
Putem verifica dacă acesta este cazul după cum urmează.
Mai întâi activați lastpipe
:
> shopt -s lastpipe
Apoi dezactivați controlul lucrărilor:
> set +m
Acum executați o comandă care setează o variabilă dintr-o țeavă:
> unset x > echo x=42 | while IFS= read -r line; do eval "${line}"; done; > echo $x 42
Observați că utilizăm while
loop și read
comanda ca o soluție, deoarece comanda eval
nu poate citi intrarea sa de la stdin (prin urmare nu poate obține intrarea de la o conductă).
Acest exemplu demonstrează că cea mai dreaptă comandă din conductă poate, de fapt , să fie executat în shell-ul curent. Cu toate acestea, acest lucru nu afectează exemplul nostru original. Chiar și cu lastpipe
activat și controlul jobului dezactivat, obținem în continuare următorul rezultat atunci când canalizăm către bash
:
> echo "x=42" | bash; echo $x >
Acest lucru se datorează faptului că comanda bash
își execută intrarea într-un subshell.
Comentarii
- aceasta este o observație bună, nu ' nu mi-am dat seama de asta, dar da, cred că ' Cum funcționează conductele
- Doar curios, care este motivul pentru care nu ați acceptat răspunsul?
- Pentru bash 4.2+ când rulați un script (sau mai exact când jobcontrol este dezactivat) și shopt
lastpipe
este setat și conducta nu are fundal, rulează capătul din dreapta al conductei în ' sus ' shell nu este un subshell. Consultați unix.stackexchange.com/questions/9954/… și unix.stackexchange.com/questions/136206/readarray-or-pipe-issue - @ dave_thompson_085 Comanda
bash
poate fi executată în shell-ul superior în funcție de opțiuni, darx=42
va fi rulat cu siguranță în ceva care poate fi numit în mod rezonabil subshell. - @AlexanderMills De fapt, conducta nu este ' t singura problemă. Comanda
bash
își va executa intrarea într-un sub-shell indiferent dacă este implicată sau nu o conductă. Consultați actualizarea soluției mele pentru mai multe detalii.
( eval 'echo "foo"' )