In Advanced Bash-Scripting Guide , in esempio 27-4 , settima riga dal basso, ho letto questo:
Una funzione viene eseguita come un sottoprocesso.
Ho fatto un test in Bash e sembra che laffermazione precedente sia sbagliata.
Ricerche su questo sito, Bash Man e il mio motore di ricerca non portano luce.
Hai la risposta e vorresti spiegarla?
Commenti
- Come notato, quella guida è estremamente fuorviante. Consiglio invece la Wooledge Bash Guide .
- Un fatto importante è che ” Bash ” evita di creare subshell. Sono costosi, hanno il tuo ambiente e quelli influenzano le prestazioni dello script e il modo in cui scorre il codice (molte volte, inconvenientemente, per gestire le loro particolarità). Lo stato attuale di Bash è il prodotto di unevoluzione, unevoluzione del codice. Voglio dire, la prima versione di Bash usa più subshell *** di quella attuale. Questo tipo di incoerenza sembra essere ragionevole. *** se vuoi una prova, non posso ‘ dartela. ‘ lho derivata da pagine web, commenti … ‘ ho letto quella dichiarazione qualche tempo fa.
Risposta
La Guida avanzata di scripting di Bash non è sempre affidabile e i suoi script di esempio contengono pratiche obsolete come luso del ha effettivamente ritirato i backtick per la sostituzione dei comandi, ovvero `command`
anziché $(command)
.
In questo caso particolare, è palesemente errato.
La sezione sulle Funzioni della shell nel Bash (canonico) il manuale afferma definitivamente che
Le funzioni della shell vengono eseguite nel contesto della shell corrente; non viene creato alcun nuovo processo per interpretarli.
Commenti
- ” Advanced Bash-Scripting Guide è generalmente inaffidabile ” Molto vero.
- Puoi fornire riferimenti per supportare il tuo prima frase?
- @WillVousden come sarebbe un riferimento qui? Alcuni esempi delle carenze tecniche della ‘? Un documento in cui gli esperti della comunità bash hanno precedentemente notato che è inaffidabile? Sarebbe utile se un membro di stackoverflow con un badge doro in bash fosse daccordo in un commento? : p
- @WillVousden Non ‘ penso che quello che vuoi esista in una forma affidabile. Mendel Cooper ha aggiornato e risolto problemi con la guida in passato, ma non esiste un bug tracker pubblico o un elenco di errata. (Forse questa è laffermazione più dannosa che posso fare.) Quindi, quando troviamo un difetto (percepito o reale) tutto ciò che possiamo fare è inviare une-mail allautore e sperare per il meglio.
- @WillVousden, .. .se vuoi una cronologia di quanto tempo il consenso nel canale freenode #bash è stato che lABS dovrebbe essere evitato, vedi wooledge.org/ ~ greybot / meta / abs – il secondo campo in ogni riga è il timestamp e il primo è il nome utente; ‘ mi auguro che laffermazione che i nomi utente in questione siano persone molto rispettate sia sufficiente.
Risposta
Le funzioni parentesi graffe verranno eseguite allinterno del processo della shell chiamante, a meno che non necessitino della propria subshell che è:
- quando vengono eseguite in background con
&
- quando li esegui come collegamento in una pipeline
Reindirizzamenti o env extra. le variabili non forzeranno una nuova sottoshell:
hw(){ echo hello world from $BASHPID echo var=$var } var=42 hw >&2 echo $BASHPID #unexports var=42 and restores stdout here
Se definisci la funzione con parentesi invece di curve:
hw()( echo hello world from $BASHPID ) hw echo $BASHPID
verrà sempre eseguito in un nuovo processo.
Sostituzione del comando $()
crea sempre processi in bash (ma non in ksh se esegui dei comandi incorporati al suo interno).
Commenti
- Non ‘ sapevo
f() (...)
è consentito. Esistono altre definizioni oltre a{...}
e(...)
? In Bash, I ‘ non mi piacciono ancora gli altri. - @tomas Puoi utilizzare la sintassi
function hw { echo hello world; }
(non è necessario()
se digitifunction
e puoi specificare i reindirizzamenti subito dopo il}
o)
come inhw(){ echo error; } >&2
. Questo è ‘. - Questo è la risposta a cui ho pensato subito, ed è assolutamente corretta.Dovrebbe essere votata come risposta corretta.
f()(...)
esegue sempre una propria shell, mentref(){...}
no. - NB le funzioni bash accettano qualsiasi comando composto, quindi
foo() [[ x = x ]]
è anche una definizione di funzione valida. Tuttavia, se guardi la funzione contype foo
‘ vedrai che questo è ancora zucchero sintattico perfoo() { [[ x = x ]]; }
. Lo stesso vale per le funzioni subshell:bar() ( : )
diventabar() { ( : ); }
. - @kojiro nice +1. ‘ non sapevo che
Rispondi
Il comando in la domanda di quellesempio è simile a:
echo ${arrayZ[@]/%e/$(replacement)}
Lesempio successivo afferma:
# $( ... ) is command substitution. # A function runs as a sub-process.
Essendo caritatevoli con ABS Guide, ciò che apparentemente intendevano scrivere è che la funzione viene eseguita allinterno di una sostituzione di comando e il comando allinterno di una sostituzione di comando viene eseguita in una subshell .
Commenti
- Questo ‘ è molto fuorviante. Grazie per la tua interpretazione.
- @tomas ” molto fuorviante. ” Sì, molto. A differenza della Guida ABS, Greg ‘ s Wiki è unottima fonte di informazioni bash avanzate.
- Saluti. Qual è la tua ‘ opinione su questo: wiki.bash-hackers.org/start ?
- @tomas Non ne ho una conoscenza di prima mano.
- @tomas, … la mia opinione sul wiki di bash-hackers è che ‘ è unottima fonte. Non ‘ lho esaminato in modo completo come il wiki di Wooledge, ma tende ad essere accurato e scritto con precisione.