Stel dat ik een bash-functie heb zoals deze:
gmx(){ echo "foo"; }
zal deze functie impliciet retourneer de exitwaarde van het echo
commando, of is het gebruik van return noodzakelijk?
gmx(){ echo "foo"; return $? }
Ik neem aan dat de manier bash werkt, de exit-status van het laatste commando van de bash-functie is degene die wordt “geretourneerd”, maar niet 100% zeker.
Antwoord
return
doet een expliciete return van een shell-functie of” dot script “(een sourced script). Als return
niet wordt uitgevoerd, wordt een impliciete return gemaakt aan het einde van de shell-functie of het punt-script.
Als return
wordt uitgevoerd zonder een parameter, het staat gelijk aan het retourneren van de exit-status van het meest recent uitgevoerde commando.
Dat is hoe return
werkt in alle POSIX shells.
Bijvoorbeeld,
gmx () { echo "foo" return "$?" }
is daarom gelijk aan
gmx () { echo "foo" return }
wat hetzelfde is als
gmx () { echo "foo" }
In het algemeen is het zeer zelden dat u $?
helemaal. Het is eigenlijk alleen nodig als u het moet opslaan voor toekomstig gebruik, bijvoorbeeld als u de waarde ervan meerdere keren moet onderzoeken (in dat geval zou u de waarde aan een variabele toewijzen en een reeks tests op die variabele uitvoeren). / p>
Opmerkingen
Antwoord
Van de bash(1)
man-pagina:
Wanneer uitgevoerd, is de exit-status van een functie de exit-status van de laatste opdracht die in de body is uitgevoerd.
Reacties
- klopt, en een logisch gevolg zou kunnen zijn dat de return-instructie niets meer is dan de exit-status?
- Ik denk
return
is een ingebouwd commando – hoewelreturn 1
anders is danexit 1
, enz. - ” return [n]: zorgt ervoor dat een functie stopt met uitvoeren en retourneert de waarde gespecificeerd door n aan zijn aanroeper. Als n wordt weggelaten, is de retourstatus die van de laatste opdracht die in de hoofdtekst van de functie is uitgevoerd. ” (ibid) Dus
return
forceert de exit-status van een functie naar een specifieke waarde indien gespecificeerd. - @AlexandwrMills Ja,
return
enexit
zijn beide ingebouwd, behalve datreturn
alleen binnen de functie kan worden gebruikt. U kunt ‘ een script niet beëindigen metreturn
. De uitgangsstatus is de waarde die de opdracht retourneert.return
is een commando dat die waarde retourneert. Dus ” return-statement is niets meer dan de exit-status ” is gewoon niet helemaal nauwkeurig. De ene is een waarde, de andere is commando plus waarde. - @AlexanderMills,
return
keert terug van de functie,exit
verlaat de hele schaal. Het ‘ is exact hetzelfde als in, zeg C metreturn
vs.exit(n)
, ofreturn
vs.sys.exit()
in Python.
Antwoord
Ik zal slechts een paar waarschuwingen toevoegen aan de reeds gegeven antwoorden:
-
Ook al heeft
return
een heel speciale betekenis voor de shell, vanuit syntaxisoogpunt is het een in de shell ingebouwd commando en een return-statement wordt geparseerd zoals elk ander eenvoudig commando. Dus dat betekent dat, net als in het argument van elk ander commando,$?
zonder aanhalingstekens onderhevig zou zijn aan split + globDus je moet dat
$?
citeren om het te vermijden:return "$?"
-
return
accepteert gewoonlijk geen “optie” (ksh93
“s accepteert de gebruikelijke--help
,--man
,--author
… echter). Het enige verwachte argument (optioneel) is de retourcode. Het bereik van geaccepteerde retourcodes varieert van shell naar shell, en of een waarde buiten 0..255 correct wordt weergegeven in
varieert ook van shell tot shell. Zie Standaard exitcode wanneer proces wordt beëindigd? voor details daarover.
De meeste shells accepteren negatieve getallen (het argument is tenslotte doorgegeven aan de _exit()
/ exitgroup()
systeemaanroep is een int
, dus met waarden die minimaal – 2 31 tot 2 31 -1, dus het is alleen maar logisch dat shells hetzelfde bereik accepteren voor hun functies).
De meeste shells gebruiken de waitpid()
en co. API om die exitstatus op te halen, maar in dat geval wordt deze afgekapt tot een getal tussen 0 en 255 wanneer opgeslagen in $?
. Ook al wordt een functie aangeroepen omvat niet het spawnen van een proces en waitpid()
gebruikt om de exitstatus op te halen aangezien alles in hetzelfde proces gebeurt, veel shells bootsen dat ook na waitpid()
gedrag bij het aanroepen van functies. Wat betekent dat zelfs als je return
aanroept met een negatieve waarde, $?
een positief getal bevat.
Onder de shells waarvan return
negatieve getallen accepteert (ksh88, ksh93, bash, zsh, pdksh en andere afgeleiden dan mksh, yash), zijn er een paar ( pdksh en yash) waarvoor het moet worden geschreven als return -- -123
omdat anders -123
wordt beschouwd als drie -1
, -2
, -3
ongeldige opties.
Zoals pdksh en zijn de rivatieven (zoals OpenBSD sh
of posh
) behouden het negatieve getal in $?
, dat betekent dat het doen van return "$?"
zou mislukken als $?
een negatief getal bevat (wat zou gebeuren wanneer de laatste opdracht een functie was die een negatief getal retourneerde ).
Dus return -- "$?"
zou beter zijn in die shells. Merk echter op dat hoewel ondersteund door de meeste shells, die syntaxis niet POSIX is en in de praktijk niet wordt ondersteund door mksh
en ash-derivaten.
Kortom, met Op pdksh gebaseerde shells mag je negatieve getallen gebruiken in argumenten voor functies, maar als je dat doet, zal return "$@"
niet “werken. In andere shells, return "$@"
werkt en u moet het gebruik van negatieve getallen (of getallen buiten 0..255) vermijden als argumenten voor return
.
In alle shells die ik ken, zal het aanroepen van return
vanuit een subshell die binnen een functie wordt uitgevoerd, ervoor zorgen dat de subshell wordt afgesloten (met de opgegeven exit-status als die er is of die van het laatste commando run), maar zal anders geen terugkeer van de functie veroorzaken (voor mij is het onduidelijk of POSIX u die garantie geeft, sommigen beweren dat exit
moet worden gebruikt in plaats van exit-subshells binnenfuncties).
f() { (return 3) echo "still inside f. Exit status: $?" } f echo "f exit status: $?"
zal bijvoorbeeld het volgende uitvoeren:
still inside f. Exit status: 3 f exit status: 0
Answer
Ja, de impliciete retourwaarde van een functie is de exitstatus van de laatste uitgevoerd commando. Dat geldt ook voor elk willekeurig shellscript. Op elk punt in de scriptuitvoeringssequentie is de huidige exitstatus de exitstatus van de laatst uitgevoerde opdracht. Even commando uitgevoerd als onderdeel van een variabeletoekenning: var=$(exit 34)
. Het verschil met functies is dat een functie de exitstatus aan het einde van de uitvoering van de functie zou kunnen veranderen.
De alternatieve manier om de “huidige exitstatus” te veranderen is door een subshell te starten en deze af te sluiten met elke benodigde exitstatus:
$ $(exit 34) $ echo "$?" 34
En ja, de exitstatus uitbreiding moeten geciteerd worden:
$ IFS="123" $ $(exit 34) $ echo $? 4
Een (exit 34)
werkt ook.
Sommigen zullen beweren dat een meer robuuste constructie $(return 34)
zou moeten zijn, en dat een exit het script dat wordt uitgevoerd zou moeten “afsluiten”. Maar $(return 34)
werkt niet met elke versie van bash. Het is dus niet draagbaar.
De veiligste manier om een exit-status in te stellen is door het te gebruiken zoals het is ontworpen om te werken, te definiëren en return
vanuit een functie :
exitstatus(){ return "${1:-"$?"}"; }
Dus aan het einde van een functie. het is exact gelijk aan ofwel niets of return
of return "$?"
. Het einde van een functie hoeft niet de “laatste coderegel van een functie” te zijn.
#!/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 }
Wordt afgedrukt:
$ ./script foo 78 baz 89 baz 90
Het enige praktische gebruik voor "$?"
is om de waarde ervan af te drukken: echo "$?"
of om op te slaan het in een variabele (aangezien het een kortstondige waarde is en verandert met elke uitgevoerde opdracht): exitstatus=$?
(vergeet niet om de variabele te citeren in opdrachten zoals export EXITSTATUS="$?"
.
In het return
commando is het geldige waardenbereik doorgaans 0 tot 255, maar begrijp dat de waarden van 126 + n
worden door sommige shells gebruikt om een speciale exit-status aan te geven, dus de algemene aanbeveling is om 0-125 te gebruiken.
return
is dat voor functies gedefinieerd alsf() (...; cmd; return)
, het voorkomt de optimalisatie die een paar shells doen door decmd
in hetzelfde proces als de subshell uit te voeren. Bij veel shells betekent dit ook dat de exitstatus van de functie niet ‘ de informatie bevat datcmd
is beëindigd wanneer het (de meeste shells kunnen ‘ die informatie toch niet ophalen).sh
ofposh
), u ‘ d hebtreturn -- "$?"
nodig als er een kans dat de laatste opdracht een functie was die een negatief getal retourneerde.mksh
(ook gebaseerd op pdksh) verbiedt functies om negatieve waarden te retourneren.return x
anders functioneert danexit x
… het enige dat ik weet is datreturn x
sluit het huidige proces niet af.return
wordt gebruikt om terug te keren van een functie of een puntenscript.exit
doet iets heel anders (beëindigt een proces).