Impliciet rendement in bash-functies?

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

  • Een nadeel van het gebruik van return is dat voor functies gedefinieerd als f() (...; cmd; return), het voorkomt de optimalisatie die een paar shells doen door de cmd 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 dat cmd is beëindigd wanneer het (de meeste shells kunnen ‘ die informatie toch niet ophalen).
  • Merk op dat met pdksh en sommige van zijn afgeleiden (zoals OpenBSD sh of posh), u ‘ d hebt return -- "$?" 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.
  • Bedankt dat dit helpt, ik denk dat ik het niet ‘ ik begrijp niet hoe return x anders functioneert dan exit x … het enige dat ik weet is dat return x sluit het huidige proces niet af.
  • @AlexanderMills Nou, het is ‘ wat ik zei: return wordt gebruikt om terug te keren van een functie of een puntenscript. exit doet iets heel anders (beëindigt een proces).
  • ja dat is logisch, ik denk dat ik hier een beter begrip van begin te krijgen

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 – hoewel return 1 anders is dan exit 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 en exit zijn beide ingebouwd, behalve dat return alleen binnen de functie kan worden gebruikt. U kunt ‘ een script niet beëindigen met return. 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 met return vs. exit(n), of return 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 + glob

    Dus 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.

    Geef een reactie

    Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *