Vad är skillnaden mellan att använda:
eval "echo "foo""
och
echo "echo "foo"" | bash
finns det något?
Kommentarer
Svar
Kort svar
Kommandot som körs av eval
körs i det aktuella skalet och kommandot som skickas till bash
körs i ett underskal, t.ex.:
> echo "x=42" | bash; echo $x > eval "x=42"; echo $x 42
Längre svar
I kommentarerna gjordes påståendet att i nyare versioner av bash
(> = 4.2) kan det första kommandot också ha samma effekt. Detta verkar dock inte vara fallet.
Det finns faktiskt ett par faktorer som gör att det pipade kommandot inte körs i den aktuella sessionen: röret och bash
kommando.
För det mesta körs piped kommandon i subshells. Bash Manual ( Avsnitt 3.2.2: Rörledningar ) har följande att säga:
Varje kommando i en pipeline körs i sin egen subshell (se Command Execution Environment ).
Som påpekats i kommentarerna kan detta beteende ändras via alternativet lastpipe
. Bash-manualen ( Avsnitt 4.3.2: Shopt Builtin ) har följande att säga om lastpipe
-alternativet:
lastpipe
Om inställt och jobbkontroll inte är aktivt kör skalet det sista kommandot för en pipeline som inte körs i bakgrund i den aktuella skalmiljön.
Vi kan verifiera att så är fallet enligt följande.
Aktivera först lastpipe
:
> shopt -s lastpipe
Inaktivera sedan jobbkontroll:
> set +m
Kör nu ett kommando som ställer in en variabel inifrån ett rör:
> unset x > echo x=42 | while IFS= read -r line; do eval "${line}"; done; > echo $x 42
Observera att vi använder while
loop och read
kommando som en lösning eftersom kommandot eval
inte kan läsa inmatningen från stdin (kan därför inte få sin input från ett rör).
Detta exempel visar att det högsta kommandot i röret faktiskt kan , köras i det aktuella skalet. Detta påverkar dock inte vårt ursprungliga exempel. Även med lastpipe
aktiverat och jobbkontroll inaktiverat får vi fortfarande följande resultat när vi rör till bash
:
> echo "x=42" | bash; echo $x >
Detta beror på att kommandot bash
själv utför sin inmatning i en subshell.
Kommentarer
- det är en bra observation, visste ' inte det, men ja jag antar att ' s hur rör fungerar
- Bara nyfiken, vad är anledningen till att du inte accepterade svaret?
- För bash 4.2+ när du kör ett skript (eller mer exakt när jobbkontroll är avstängd) och shopt
lastpipe
är inställt och rörledningen har ingen bakgrund, den kör den högra änden av röret i ' topp ' skal inte en subshell. Se unix.stackexchange.com/questions/9954/… och unix.stackexchange.com/questions/136206/readarray-or-pipe-issue - @ dave_thompson_085 Kommandot
bash
kan köras i det övre skalet beroende på alternativ, menx=42
kommer säkert att köras i något som rimligen kan kallas en subshell. - @AlexanderMills Egentligen är röret inte ' t enda problemet. Kommandot
bash
kommer att utföra dess ingång i en subshell oavsett om ett rör är inblandat eller inte. Se uppdateringen av min lösning för mer information.
( eval 'echo "foo"' )