Hvad er forskellen mellem at bruge:
eval "echo "foo""
og
echo "echo "foo"" | bash
er der nogen?
Kommentarer
Svar
Kort svar
Kommandoen, der køres af eval
, udføres i den aktuelle shell, og kommandoen, der sendes til bash
, udføres i en sub-shell, f.eks:
> echo "x=42" | bash; echo $x > eval "x=42"; echo $x 42
Længere svar
I kommentarerne blev kravet fremsat om, at i nyere versioner af bash
(> = 4.2) kunne den første kommando også have den samme effekt. Dette ser dog ikke ud til at være tilfældet.
Der er faktisk et par faktorer, der får den pipede kommando til ikke at køre i den aktuelle session: røret og bash
kommando.
For det meste kører piped-kommandoer i subshells. Bash Manual ( Afsnit 3.2.2: Rørledninger ) har følgende at sige:
Hver kommando i en pipeline udføres i sin egen subshell (se Kommandoudførelsesmiljø ).
Som påpeget i kommentarerne, kan denne adfærd ændres via indstillingen lastpipe
. Bash-manualen ( Afsnit 4.3.2: Shopt Builtin ) har følgende at sige om lastpipe
-muligheden:
lastpipe
Hvis indstillet, og jobkontrol ikke er aktiv, kører shell den sidste kommando af en pipeline, der ikke udføres i baggrund i det aktuelle shell-miljø.
Vi kan kontrollere, at dette er tilfældet som følger.
Aktivér først lastpipe
:
> shopt -s lastpipe
Deaktiver derefter jobkontrol:
> set +m
Udfør nu en kommando, der indstiller en variabel fra et rør:
> unset x > echo x=42 | while IFS= read -r line; do eval "${line}"; done; > echo $x 42
Bemærk, at vi bruger while
loop og read
kommando som en omgåelse, da kommandoen eval
ikke kan læse dens input fra stdin (kan derfor ikke få sin input fra et rør).
Dette eksempel viser, at den rigtigste kommando i røret faktisk kan , udføres i den aktuelle skal. Dette påvirker imidlertid ikke vores oprindelige eksempel. Selv med lastpipe
aktiveret og jobkontrol deaktiveret, får vi stadig følgende resultat, når vi rør til bash
:
> echo "x=42" | bash; echo $x >
Dette skyldes, at bash
selve kommandoen udfører sin input i en subshell.
Kommentarer
- det er en god observation, forstod ' det ikke, men ja, jeg antager at ' s hvordan rør fungerer
- Bare nysgerrig, hvad er grunden til, at du ikke accepterede svaret?
- For bash 4.2+, når du kører et script (eller mere præcist, når jobkontrol er slået fra) og shopt
lastpipe
er indstillet, og rørledningen har ikke baggrund, den kører den højre ende af røret i ' top ' shell ikke en subshell. Se unix.stackexchange.com/questions/9954/… og unix.stackexchange.com/questions/136206/readarray-or-pipe-issue - @ dave_thompson_085 Kommandoen
bash
kan udføres i den øverste skal afhængigt af mulighederne, menx=42
vil helt sikkert blive kørt i noget, der med rimelighed kan kaldes en subshell. - @AlexanderMills Faktisk er røret ikke ' t det eneste problem. Kommandoen
bash
udfører dens input i en subshell uanset om et rør er involveret. Se opdateringen til min løsning for flere detaljer.
( eval 'echo "foo"' )