eval vs. pipe tramite bash

Qual è la differenza tra lutilizzo di:

eval "echo "foo"" 

e

echo "echo "foo"" | bash 

ce nè?

Commenti

  • Ecco ' unaltra variazione con un comportamento leggermente diverso per quanto riguarda gli ambienti di esecuzione: ( eval 'echo "foo"' )

Risposta

Risposta breve

Il comando eseguito da eval viene eseguito nella shell corrente e il comando reindirizzato a bash viene eseguito in una sotto-shell, ad esempio:

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

Risposta più lunga

Nei commenti è stato affermato che nelle versioni più recenti di bash (> = 4.2) anche il primo comando potrebbe avere lo stesso effetto. Tuttavia questo non sembra essere il caso.

In realtà ci sono un paio di fattori che impediscono lesecuzione del comando piped nella sessione corrente: la pipe e il bash.

Per la maggior parte, i comandi in pipe vengono eseguiti in subshell. Il manuale Bash ( Sezione 3.2.2: Pipeline ) dice quanto segue:

Ogni comando in una pipeline viene eseguito nella propria sottoshell (vedere Ambiente di esecuzione dei comandi ).

Come sottolineato nei commenti, questo comportamento può essere modificato tramite lopzione lastpipe. Il manuale Bash ( Sezione 4.3.2: Shopt Builtin ) ha da dire quanto segue sullopzione lastpipe:

lastpipe

Se impostato e il controllo del lavoro non è attivo, la shell esegue lultimo comando di una pipeline non eseguita nella background nellambiente shell corrente.

Possiamo verificare che questo sia il caso come segue.

Innanzitutto abilita lastpipe:

> shopt -s lastpipe 

Quindi disabilita il controllo del lavoro:

> set +m 

Ora esegui un comando che imposta una variabile dallinterno di una pipe:

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

Notare che usiamo while loop e read come soluzione alternativa poiché il comando eval non può leggere il suo input da stdin (quindi non può ottenere il suo input da una pipe).

Questo esempio dimostra che il comando più a destra nella pipe può, in effetti , essere eseguito nella shell corrente. Tuttavia ciò non influisce effettivamente sul nostro esempio originale. Anche con lastpipe abilitato e il controllo del lavoro disabilitato, otteniamo comunque il seguente risultato quando ci colleghiamo a bash:

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

Questo perché il comando bash stesso esegue il suo input in una subshell.

Commenti

  • questa è una buona osservazione, ' non se ne rendeva conto, ma sì, immagino che ' s come funzionano le pipe
  • Sono solo curioso, qual è il motivo per cui non hai accettato la risposta?
  • Per bash 4.2+ durante lesecuzione di uno script (o più esattamente quando jobcontrol è disattivato) e shopt lastpipe è impostato e la pipeline non è in background, esegue lestremità destra della pipe in ' in alto ' shell non è una subshell. Vedi unix.stackexchange.com/questions/9954/… e unix.stackexchange.com/questions/136206/readarray-or-pipe-issue
  • @ dave_thompson_085 Il comando bash può essere eseguito in la shell superiore a seconda delle opzioni, ma x=42 verrà sicuramente eseguita in qualcosa che può ragionevolmente essere chiamata subshell.
  • @AlexanderMills In realtà, la pipe non è ' t lunico problema. Il comando bash eseguirà il suo input in una subshell indipendentemente dal fatto che sia coinvolta o meno una pipe. Vedi laggiornamento alla mia soluzione per maggiori dettagli.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *