Supponiamo di avere una funzione bash in questo modo:
gmx(){ echo "foo"; }
questa funzione sarà implicita restituire il valore di uscita del comando echo
o è necessario utilizzare return?
gmx(){ echo "foo"; return $? }
presumo che il modo bash funziona, lo stato di uscita del comando finale della funzione bash è quello che viene “restituito”, ma non certo al 100%.
Risposta
return
restituisce esplicito da una funzione di shell o” dot script “(uno script originato). Se return
non viene eseguito, viene eseguito un ritorno implicito alla fine della funzione shell o del dot script.
Se return
viene eseguito senza un parametro, equivale a restituire lo stato di uscita del comando eseguito più di recente.
Ecco come funziona return
in tutti i POSIX shell.
Ad esempio,
gmx () { echo "foo" return "$?" }
è quindi equivalente a
gmx () { echo "foo" return }
che è uguale a
gmx () { echo "foo" }
In generale, è molto raro che tu abbia bisogno di utilizzare $?
affatto. È davvero necessario solo se è necessario salvarlo per un utilizzo futuro, ad esempio se è necessario indagare più volte sul suo valore (nel qual caso si assegnerebbe il suo valore a una variabile ed eseguire una serie di test su quella variabile).
Commenti
Risposta
Dalla pagina man bash(1)
:
Quando viene eseguito, lo stato di uscita di una funzione è lo stato di uscita dellultimo comando eseguito nel corpo.
Commenti
- giusto, e un corollario potrebbe essere che listruzione return non è altro che lo stato di uscita?
- Immagino
return
è un comando incorporato, sebbenereturn 1
sia diverso daexit 1
, ecc. - ” return [n]: fa sì che una funzione interrompa lesecuzione e restituisca il valore specificato da n al suo chiamante. Se n viene omesso, lo stato di ritorno è quello dellultimo comando eseguito nel corpo della funzione. ” (ibid) Quindi,
return
forza lo stato di uscita di una funzione a un valore specifico, se specificato. - @AlexandwrMills Sì,
return
eexit
sono entrambi integrati, eccetto chereturn
può essere utilizzato solo allinterno della funzione. Non puoi ‘ terminare uno script conreturn
. Lo stato di uscita è il valore restituito dal comando.return
è il comando che restituisce quel valore. Quindi listruzione ” return non è altro che lo stato di uscita ” non è abbastanza preciso. Uno è un valore, laltro è il comando più il valore. - @AlexanderMills,
return
restituisce dalla funzione,exit
esce dallintera shell. ‘ è esattamente uguale a, ad esempio C conreturn
eexit(n)
, oreturn
esys.exit()
in Python.
Risposta
Aggiungerò solo alcune note di cautela alle risposte già fornite:
-
Anche se
return
ha un significato molto speciale per la shell, dal punto di vista della sintassi è un comando incorporato della shell e unistruzione return viene analizzato come qualsiasi altro comando semplice. Quindi, ciò significa che come nellargomento di qualsiasi altro comando,$?
se non quotato, sarebbe soggetto a split + globQuindi devi citarne
$?
per evitarlo:return "$?"
-
return
di solito non “accetta alcuna opzione (ksh93
” s accetta il solito--help
,--man
,--author
… però). Lunico argomento che si aspetta (facoltativo) è il codice di ritorno. Lintervallo di codici di ritorno accettati varia da shell a shell e se qualsiasi valore al di fuori di 0..255 si riflette correttamente in
varia anche da shell a shell. Vedi Codice di uscita predefinito quando il processo viene terminato? per i dettagli.
La maggior parte delle shell accetta numeri negativi (dopotutto, largomento passato a la _exit()
/ exitgroup()
chiamata di sistema è una int
, quindi con valori che comprendono almeno – 2 31 a 2 31 -1, quindi ha senso che le shell accettino lo stesso intervallo per le sue funzioni).
La maggior parte delle shell usa il waitpid()
e co. API per recuperare lo stato di uscita, tuttavia, in tal caso, viene troncato a un numero compreso tra 0 e 255 quando memorizzato in $?
. Anche se si richiama una funzione non comporta la generazione di un processo e utilizza waitpid()
per recuperare il suo stato di uscita poiché tutto viene eseguito nello stesso processo, molte shell imitano anche questo waitpid()
comportamento durante la chiamata di funzioni. Ciò significa che anche se chiami return
con un valore negativo, $?
conterrà un numero positivo.
Ora, tra quelle shell la cui return
accetta numeri negativi (ksh88, ksh93, bash, zsh, pdksh e derivati diversi da mksh, yash), ce ne sono alcuni ( pdksh e yash) che richiedono che sia scritto come return -- -123
altrimenti -123
viene considerato come tre -1
, -2
, -3
opzioni non valide.
Come pdksh e il suo de i rivativi (come OpenBSD sh
o posh
) conservano il numero negativo in $?
, che significa che fare return "$?"
fallirebbe quando $?
contiene un numero negativo (cosa che accadrebbe quando lultimo comando eseguito era una funzione che restituiva un numero negativo ).
Quindi return -- "$?"
sarebbe meglio con quelle shell. Tuttavia si noti che sebbene supportata dalla maggior parte delle shell, tale sintassi non è POSIX e in pratica non è supportata da mksh
e dai derivati di ash.
Quindi, per riassumere, con shell basate su pdksh, puoi utilizzare numeri negativi negli argomenti delle funzioni, ma se lo fai, return "$@"
non funzionerà. In altre shell, return "$@"
funzionerà e dovresti evitare di utilizzare numeri negativi (o numeri al di fuori di 0..255) come argomenti per return
.
In tutte le shell che conosco, chiamare return
dallinterno di una subshell in esecuzione allinterno di una funzione causerà luscita della subshell (con lo stato di uscita fornito se presente o quello dellultimo comando run), ma altrimenti non causerà un ritorno dalla funzione (per me, non è chiaro se POSIX ti dà quella garanzia, alcuni sostengono che exit
dovrebbe essere usato al posto delle subshell di uscita funzioni interne). Ad esempio
f() { (return 3) echo "still inside f. Exit status: $?" } f echo "f exit status: $?"
restituirà:
still inside f. Exit status: 3 f exit status: 0
Risposta
Sì, il valore di ritorno implicito di una funzione è lo stato di uscita dellultima eseguita . Questo vale anche in qualsiasi punto di qualsiasi script di shell. In qualsiasi punto della sequenza di esecuzione dello script, lo stato di uscita attuale è lo stato di uscita dellultimo comando eseguito. Comando pari eseguito come parte dellassegnazione di una variabile: var=$(exit 34)
. La differenza con le funzioni è che una funzione potrebbe cambiare lo stato di uscita alla fine dellesecuzione della funzione.
Il modo alternativo per cambiare lo “stato di uscita attuale” è avviare una sub shell e uscirne con qualsiasi stato di uscita necessario:
$ $(exit 34) $ echo "$?" 34
E sì, lo stato di uscita espansione deve essere citato:
$ IFS="123" $ $(exit 34) $ echo $? 4
Un (exit 34)
funziona anche.
Alcuni potrebbero sostenere che un costrutto più robusto dovrebbe essere $(return 34)
e che unuscita dovrebbe “uscire” dallo script in esecuzione. Tuttavia, $(return 34)
non funziona con qualsiasi versione di bash. Quindi, non è portabile.
Il modo più sicuro per impostare uno stato di uscita è usarlo poiché è stato progettato per funzionare, definire e return
da una funzione :
exitstatus(){ return "${1:-"$?"}"; }
Quindi, alla fine di una funzione. è esattamente equivalente a non avere niente o return
o return "$?"
. La fine di una funzione non deve necessariamente significare “lultima riga di codice di una funzione”.
#!/bin/sh exitstatus(){ a="${1:-"$?"}"; return "$a"; } gmx(){ if [ "$1" = "one" ]; then printf "foo "; exitstatus 78 return "$?" elif [ "$1" = "two" ]; then printf "baz "; exitstatus 89 return else printf "baz "; exitstatus 90 fi }
Stamperà:
$ ./script foo 78 baz 89 baz 90
Lunico utilizzo pratico di "$?"
è stamparne il valore: echo "$?"
o memorizzare in una variabile (poiché è un valore effimero e cambia ad ogni comando eseguito): exitstatus=$?
(ricordati di citare la variabile in comandi come export EXITSTATUS="$?"
.
Nel comando return
, lintervallo di valori valido è generalmente compreso tra 0 e 255, ma tieni presente che i valori di 126 + n
sono usati da alcune shell per segnalare uno stato di uscita speciale, quindi la raccomandazione generale è di usare 0-125.
return
è che per funzioni definite comef() (...; cmd; return)
, impedisce lottimizzazione eseguita da alcune shell per eseguirecmd
nello stesso processo della subshell. Con molte shell, ciò significa anche che lo stato di uscita della funzione non ‘ porta le informazioni checmd
è stato terminato quando è stato (la maggior parte delle shell può ‘ recuperare comunque tali informazioni).sh
oposh
), ‘ avresti bisogno direturn -- "$?"
se cera un possibilità che lultimo comando fosse una funzione che ha restituito un numero negativo.mksh
(basato anche su pdksh) vieta alle funzioni di restituire valori negativi.return x
funzioni in modo diverso daexit x
… lunica cosa che so è chereturn x
non uscirà dal processo corrente.return
viene utilizzato per tornare da una funzione o da uno script punto.exit
fa qualcosa di completamente diverso (termina un processo).