Qual è la differenza tra lutilizzo di:
eval "echo "foo""
e
echo "echo "foo"" | bash
ce nè?
Commenti
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, max=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.
( eval 'echo "foo"' )