eval vs. pipe through bash (Română)

Care este diferența dintre utilizarea:

eval "echo "foo"" 

și

echo "echo "foo"" | bash 

există vreunul?

Comentarii

  • Aici ' este o altă variantă cu un comportament ușor diferit în ceea ce privește mediile de execuție: ( eval 'echo "foo"' )

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, dar x=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.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *