Kör funktioner som underprocesser i Bash?

I Advanced Bash-Scripting Guide , i exempel 27-4 , 7: e raden från botten, jag har läst det här:

En funktion körs som en delprocess.

Jag gjorde ett test i Bash, och det verkar som att ovanstående uttalande är fel.

Söker på den här webbplatsen, Bash Man, och min sökmotor ger inget ljus.

Har du svaret och vill förklara?

Kommentarer

  • Som nämnts är guiden extremt vilseledande. Jag rekommenderar Wooledge Bash Guide istället.
  • Ett viktigt faktum är att ” Bash ” undviker att skapa subshells. De är dyra, har din egen miljö och de påverkar skriptets prestanda och hur koden flyter (många gånger, obekvämt, för att hantera deras särdrag). Det faktiska tillståndet för Bash är en produkt av en utveckling, en kodutveckling. Jag menar, den första versionen av Bash använder fler subshells *** än den faktiska. Denna typ av inkonsekvens verkar vara rimlig. *** om du vill ha ett bevis kan jag ’ inte ge dig. Jag ’ har härledt det från webbsidor, kommentarer … Jag ’ har läst det uttalandet någonstans någon gång sedan.

Svar

Advanced Bash-Scripting Guide är inte alltid tillförlitlig och dess exempelskript innehåller föråldrade metoder som att använda utfas effektivt backticks för kommandosubstitution, dvs. `command` snarare än $(command).

I det här fallet är det uppenbart felaktigt.

Avsnittet om Skalfunktioner i (kanonisk) Bash i manualen anges definitivt att

Shell-funktioner körs i det aktuella skalkontextet; ingen ny process skapas för att tolka dem.

Kommentarer

  • ” Advanced Bash-Scripting Guide är i allmänhet opålitlig ” Mycket sant.
  • Kan du ge referenser för att stödja din första meningen?
  • @WillVousden hur skulle en referens se ut här? Ett gäng exempel på guiden ’ tekniska brister? Ett dokument där experter i bash-samhället tidigare har noterat att det är opålitligt? Skulle det hjälpa om en stackoverflow-medlem med ett guldmärke i bash bara kom överens i en kommentar? : p
  • @WillVousden Jag ’ tänker inte att det du vill finns i en pålitlig form i sig. Mendel Cooper har uppdaterat och fixat problem med guiden tidigare, men det finns ingen offentlig bugspårare eller lista med errata. (Det kanske är det mest fördömande uttalandet jag kan göra.) Så när vi hittar en brist (upplevd eller verklig) är allt vi kan göra att skicka e-post till författaren och hoppas på det bästa.
  • @WillVousden, .. .om du vill ha en historik om hur länge konsensus i freenode #bash-kanalen har varit att ABS ska undvikas, se wooledge.org/ ~ greybot / meta / abs – det andra fältet i varje rad är tidsstämpeln, och det första är användarnamnet; Jag ’ jag hoppas att påståendet att användarnamnen i fråga är mycket respekterade individer räcker.

Svar

Curly brace-funktioner körs inom den anropande skalprocessen, såvida de inte behöver sin egen subshell som är:

  • när du kör dem i bakgrunden med &
  • när du kör dem som en länk i en pipeline

Omdirigeringar eller extra env. variabler tvingar inte ett nytt subshell:

hw(){ echo hello world from $BASHPID echo var=$var } var=42 hw >&2 echo $BASHPID #unexports var=42 and restores stdout here 

Om du definierar funktionen med parenteser istället för curlies:

hw()( echo hello world from $BASHPID ) hw echo $BASHPID 

den körs alltid i en ny process.

Kommandosubstitution $() skapar också alltid processer i bash (men inte i ksh om du kör inbyggda inuti den).

Kommentarer

  • Jag visste inte ’ visste inte f() (...) är tillåtet. Finns det andra definitioner förutom {...} och (...)? I Bash, I ’ inte till andra än.
  • @tomas Du kan använda function hw { echo hello world; } syntax (inget behov av () om du skriver ut function och du kan ange omdirigeringar direkt efter den sista } eller ) som i hw(){ echo error; } >&2. Att ’ handlar om det.
  • Det här är svaret som jag genast tänkte på, och det är helt korrekt.Det bör röstas som rätt svar. f()(...) kör alltid ett eget skal, medan f(){...} inte gör det.
  • OBS bash-funktioner accepterar något sammansatt kommando, så foo() [[ x = x ]] är också en giltig funktionsdefinition. Men om du tittar på funktionen med type foo ser du ’ att detta fortfarande är syntaktiskt socker för foo() { [[ x = x ]]; }. Detsamma gäller subshell-funktioner: bar() ( : ) blir bar() { ( : ); }.
  • @kojiro trevligt +1. visste ’ inte det

Svar

Kommandot i frågan från det exemplet ser ut som:

echo ${arrayZ[@]/%e/$(replacement)} 

I exemplet anges senare:

# $( ... ) is command substitution. # A function runs as a sub-process. 

Att vara välgörenhet mot ABS Guide, vad de tydligen menade att skriva är att funktionen körs i en kommandosubstitution och kommandot inuti en kommandosubstitution körs i en subshell .

Kommentarer

  • Att ’ är mycket missvisande. Tack för din tolkning.
  • @tomas ” mycket missvisande. ” Ja, mycket. Till skillnad från ABS-guiden är Greg ’ s Wiki en utmärkt källa till avancerad basinformation.
  • Skål. Vad ’ är din åsikt om den här: wiki.bash-hackers.org/start ?
  • @tomas Jag har ingen förstahands kunskap om den.
  • @tomas, … min egen åsikt om bash-hackers wiki är att den ’ är en utmärkt källa. Jag har inte ’ inte gått igenom den lika omfattande som jag har Wooledge-wiki, men den tenderar att vara korrekt och exakt skriven.

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *