Implicit afkast i bash-funktioner?

Sig, at jeg har en bash-funktion som sådan:

gmx(){ echo "foo"; } 

vil denne funktion implicit returnere exitværdien af kommandoen echo, eller er det nødvendigt at bruge return?

gmx(){ echo "foo"; return $? } 

Jeg antager, at vejen bash fungerer, udgangsstatus for den endelige kommando af bash-funktionen er den, der bliver “returneret”, men ikke 100% sikker.

Svar

return returnerer en eksplicit fra en shell-funktion eller” dot script “(et sourcet script). Hvis return ikke udføres, foretages der en implicit retur i slutningen af shell-funktionen eller dot-scriptet.

Hvis return udføres uden en parameter, det svarer til at returnere exit-status for den senest udførte kommando.

Sådan fungerer return i alle POSIX skaller.

For eksempel,

gmx () { echo "foo" return "$?" } 

svarer derfor til

gmx () { echo "foo" return } 

hvilket er det samme som

gmx () { echo "foo" } 

Generelt er det meget sjældent, at du skal bruge $? overhovedet. Det er virkelig kun nødvendigt, hvis du har brug for at gemme det til fremtidig brug, for eksempel hvis du har brug for at undersøge dens værdi flere gange (i hvilket tilfælde du vil tildele dens værdi til en variabel og udføre en række tests på den variabel). / p>

Kommentarer

  • En ulempe ved at bruge return er, at for funktioner defineret som f() (...; cmd; return) forhindrer det den optimering, som nogle få skaller gør for at køre cmd i samme proces som subshell. Med mange skaller betyder det også, at funktionens udgangsstatus ikke ‘ t bærer den information, at cmd er dræbt, når den er (de fleste skaller kan ‘ ikke hente disse oplysninger alligevel).
  • Bemærk, at med pdksh og nogle af dets derivater (som OpenBSD sh eller posh), du ‘ d har brug for return -- "$?" hvis der var en chance for, at den sidste kommando var en funktion, der returnerede et negativt tal. mksh (også baseret på pdksh) forbyder funktioner at returnere negative værdier.
  • tak, dette hjælper, jeg tror ikke jeg ‘ t forstår hvordan return x fungerer anderledes end exit x … det eneste jeg ved er at return x afslutter ikke den nuværende proces.
  • @AlexanderMills Nå, det ‘ er hvad jeg sagde: return bruges til at vende tilbage fra en funktion eller et punkt script. exit gør noget helt andet (afslutter en proces).
  • ja det giver mening Jeg tror, jeg begynder at få et bedre håndtag på dette

Svar

Fra bash(1) mandesiden:

Når den udføres, er udgangsstatus for en funktion udgangsstatus for den sidste kommando, der blev udført i kroppen.

Kommentarer

  • rigtigt, og en konsekvens kan være, at returerklæringen ikke er mere end exitstatus?
  • Jeg gætter return er en indbygget kommando – skønt return 1 er forskellig fra exit 1 osv. Så
  • ” return [n]: Forårsager en funktion til at stoppe udførelsen og returnere den værdi, der er specificeret af n, til dens opkald. Hvis n udelades, er returstatus den for den sidste kommando, der blev udført i funktionslegemet. ” (ibid) return tvinger en funktions udgangsstatus til en bestemt værdi, hvis det er angivet.
  • @AlexandwrMills Ja, return og exit er begge indbyggede, undtagen return kan kun bruges inden for funktion. Du kan ‘ t opsige et script med return. Udgangsstatus er værdi, som kommandoen returnerer. return er en kommando, der returnerer denne værdi. Så ” returneringserklæring er intet andet end exitstatus ” er bare ikke helt nøjagtig. Den ene er en værdi, den anden er kommando plus værdi.
  • @AlexanderMills, return vender tilbage fra funktionen, exit går ud af hele skallen. Det ‘ er nøjagtigt det samme som i, sig C med return vs. exit(n), eller return vs. sys.exit() i Python.

Svar

Jeg tilføjer blot et par noter med forsigtighed til de allerede leverede svar:

  • Selvom return har en meget speciel betydning for skallen, set fra et syntaks synspunkt, er det en shell-indbygget kommando og en returerklæring er analyseret som enhver anden simpel kommando. Så det betyder, at som i argumentet for enhver anden kommando, $? når den ikke er citeret, vil være underlagt split + glob

    Så du skal citere det $? for at undgå det:

    return "$?" 
  • return accepterer normalt ikke nogen mulighed (ksh93 “s accepterer den sædvanlige --help, --man, --author … dog). Det eneste argument, det forventer (valgfrit) er returkoden. Omfanget af accepterede returkoder varierer fra skal til skal, og om en værdi uden for 0..255 afspejles korrekt i

varierer også fra shell til shell. Se Standardudgangskode, når processen afsluttes? for detaljer om det.

De fleste skaller accepterer negative tal (trods alt overføres argumentet til _exit() / exitgroup() systemopkald er et int, så værdierne omfatter mindst – 2 31 til 2 31 -1, så det giver kun mening, at skaller accepterer det samme område for dets funktioner).

De fleste skaller bruger waitpid() og co. API for at hente denne udgangsstatus, men i hvilket tilfælde er den afkortet til et tal mellem 0 og 255, når gemt i $?. Selvom der påberåbes en funktion involverer ikke gydning af en proces og brugte waitpid() til at hente sin exitstatus, da alt er gjort i samme proces, mange skaller efterligner også at waitpid() adfærd ved påkald af funktioner. Hvilket betyder, at selvom du kalder return med en negativ værdi, vil $? indeholde et positivt tal.

Nu blandt de skaller, hvis return accepterer negative tal (ksh88, ksh93, bash, zsh, pdksh og andre derivater end mksh, yash), er der et par ( pdksh og yash) som har brug for det skrevet som return -- -123 da ellers at -123 tages som tre -1, -2, -3 ugyldige indstillinger.

Som pdksh og dens de rivativer (som OpenBSD sh eller posh) bevarer det negative tal i $?, det betyder at udføre return "$?" ville mislykkes, når $? indeholder et negativt tal (hvilket ville ske, når kommandoen til sidste kørsel var en funktion, der returnerede et negativt tal ).

return -- "$?" ville være bedre i disse skaller. Bemærk dog, at mens syntaks understøttes af de fleste skaller, ikke er POSIX og i praksis ikke understøttes af mksh og askerivater.

Så for at opsummere med pdksh-baserede skaller, kan du bruge negative tal i argumenter til funktioner, men hvis du gør det, return "$@" fungerer ikke. I andre skaller fungerer return "$@" fungerer, og du bør undgå at bruge negative tal (eller tal uden for 0..255) som argumenter for return.

  • I alle skaller, jeg kender, kalder return indefra en subshell, der kører inde i en funktion, får subshell til at afslutte (med den angivne exit-status, hvis nogen eller den af den sidste kommando run), men vil ellers ikke medføre en tilbagevenden fra funktionen (for mig er det uklart, om POSIX giver dig den garanti, nogle hævder, at exit skal bruges i stedet for at afslutte subshells indvendige funktioner). For eksempel

    f() { (return 3) echo "still inside f. Exit status: $?" } f echo "f exit status: $?" 

    vil output:

    still inside f. Exit status: 3 f exit status: 0 
  • Svar

    Ja, den implicitte returværdi af en funktion er udgangsstatus for den sidste udført kommando. Det gælder også når som helst i ethvert shell-script. På ethvert tidspunkt i sekvensen for eksekvering af script er den nuværende exitstatus exitstatus for den sidst udførte kommando. Selv kommando udført som en del af en variabel tildeling: var=$(exit 34). Forskellen med funktioner er, at en funktion kan ændre udgangsstatus i slutningen af udførelsen af funktionen.

    Den alternative måde at ændre den “nuværende udgangsstatus” er at starte en underskal og afslutte den med enhver nødvendig udgangsstatus:

    $ $(exit 34) $ echo "$?" 34 

    Og ja, udgangsstatus udvidelse skal citeres:

    $ IFS="123" $ $(exit 34) $ echo $? 4 

    En (exit 34) fungerer også.
    Nogle kan argumentere for, at en mere robust konstruktion skal være $(return 34), og at en exit skal “afslutte” det script, der udføres. Men $(return 34) fungerer ikke med nogen version af bash. Så den er ikke bærbar.

    Den sikreste måde at indstille en exit-status på er at bruge den, da den var designet til at arbejde, definere og return fra en funktion :

    exitstatus(){ return "${1:-"$?"}"; } 

    Så i slutningen af en funktion. det svarer nøjagtigt til at have enten intet eller return eller return "$?". Slutningen af en funktion behøver ikke at betyde den “sidste kodelinje for en funktion”.

    #!/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 } 

    Udskrives:

    $ ./script foo 78 baz 89 baz 90 

    Den eneste praktiske anvendelse til "$?" er at enten udskrive dens værdi: echo "$?" eller at gemme det i en variabel (da det er en kortvarig værdi og ændring med hver kommando, der udføres): exitstatus=$? (husk at citere variablen i kommandoer som export EXITSTATUS="$?".

    I kommandoen return er det gyldige værdiområde generelt 0 til 255, men forstå, at værdierne for 126 + n bruges af nogle skaller til at signalere en særlig udgangsstatus, så den generelle anbefaling er at bruge 0-125.

    Skriv et svar

    Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *