eval vs. rør gennem bash

Hvad er forskellen mellem at bruge:

eval "echo "foo"" 

og

echo "echo "foo"" | bash 

er der nogen?

Kommentarer

  • Her er ' en anden variation med lidt anderledes adfærd med hensyn til eksekveringsmiljøer: ( eval 'echo "foo"' )

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

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *