Implisitt avkastning i bash-funksjoner?

Si at jeg har en bash-funksjon slik:

gmx(){ echo "foo"; } 

vil denne funksjonen implisitt returnere utgangsverdien til echo -kommandoen, eller er det nødvendig å bruke retur?

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

Jeg antar at veien bash fungerer, utgangsstatusen for den endelige kommandoen til bash-funksjonen er den som blir «returnert», men ikke 100% sikker.

Svar

return returnerer en eksplisitt fra en skallfunksjon eller» prikkskript «(et hentet skript). Hvis return ikke utføres, blir det gitt en implisitt avkastning på slutten av skallfunksjonen eller punktskriptet.

Hvis return kjøres uten en parameter, det tilsvarer å returnere utgangsstatus for den sist utførte kommandoen.

Det er slik return fungerer i alle POSIX skjell.

For eksempel,

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

tilsvarer derfor

gmx () { echo "foo" return } 

som er det samme som

gmx () { echo "foo" } 

Generelt sett er det veldig sjelden du trenger å bruke $? i det hele tatt. Det er egentlig bare nødvendig hvis du trenger å lagre det for fremtidig bruk, for eksempel hvis du trenger å undersøke verdien flere ganger (i så fall vil du tilordne verdien til en variabel og utføre en serie tester på den variabelen). / p>

Kommentarer

  • En ulempe ved å bruke return er at for funksjoner definert som f() (...; cmd; return), forhindrer det optimaliseringen som noen få skjell gjør for å kjøre cmd i samme prosess som subshell. Med mange skall betyr det også at utgangsstatusen til funksjonen ikke ‘ t bærer informasjonen om at cmd er drept når den har (de fleste skjell kan ‘ t hente informasjonen uansett).
  • Merk at med pdksh og noen av dets derivater (som OpenBSD sh eller posh), du ‘ d trenger return -- "$?" hvis det var sjanse for at den siste kommandoen var en funksjon som returnerte et negativt tall. mksh (også basert på pdksh) forbyr funksjoner å returnere negative verdier.
  • takk for at dette hjelper, antar at jeg ikke ‘ t forstår hvordan return x fungerer annerledes enn exit x … det eneste jeg vet er at return x vil ikke avslutte den nåværende prosessen.
  • @AlexanderMills Vel, det ‘ er det jeg sa: return brukes til å returnere fra en funksjon eller et punktskript. exit gjør noe helt annet (avslutter en prosess).
  • ja det gir mening Jeg tror jeg begynner å få et bedre håndtak på dette

Svar

Fra bash(1) man-siden:

Når den utføres, er utgangsstatus for en funksjon utgangsstatus for den siste kommandoen som ble utført i kroppen.

Kommentarer

  • riktig, og en følge kan være at returuttalelsen ikke er noe mer enn utgangsstatusen?
  • Jeg antar return er en innebygd kommando – selv om return 1 er annerledes enn exit 1 osv. Så
  • » return [n]: Gjør at en funksjon stopper utførelsen og returnerer verdien som er spesifisert av n til den som ringer. Hvis n er utelatt, er returstatusen den for den siste kommandoen som ble utført i funksjonslegemet. » (ibid) Så, return tvinger utgangsstatusen til en funksjon til en bestemt verdi hvis spesifisert.
  • @AlexandwrMills Ja, return og exit er begge innebygde, bortsett fra at return bare kan brukes innen funksjon. Du kan ‘ t avslutte et skript med return. Utgangsstatus er verdien kommandoen returnerer. return er en kommando som returnerer den verdien. Så » returuttalelse er ikke noe mer enn utgangsstatus » er bare ikke helt nøyaktig. Den ene er en verdi, den andre er kommando pluss verdi.
  • @AlexanderMills, return returnerer fra funksjonen, exit går ut av hele skallet. Det ‘ er nøyaktig det samme som i, si C med return vs. exit(n), eller return vs. sys.exit() i Python.

Svar

Jeg legger bare til noen forsiktighetsanvisninger i svarene som allerede er gitt:

  • Selv om return har en veldig spesiell betydning for skallet, fra et syntakssynspunkt er det en shell-innebygd kommando og en returuttalelse blir analysert som alle andre enkle kommandoer. Så det betyr at $? når det ikke er sitert, vil bli utsatt for split + glob

    Så du må sitere det $? for å unngå det:

    return "$?" 
  • return godtar vanligvis ikke noe alternativ (ksh93 «s godtar det vanlige --help, --man, --author … skjønt). Det eneste argumentet det forventer (valgfritt) er returkoden. Omfanget av aksepterte returkoder varierer fra skall til skall, og om noen verdi utenfor 0..255 gjenspeiles riktig i

varierer også fra skall til skall. Se Standard utgangskode når prosessen avsluttes? for detaljer om det.

De fleste skjell godtar negative tall (tross alt overføres argumentet til _exit() / exitgroup() systemanrop er en int, så med verdier som omfatter minst – 2 31 til 2 31 -1, så det er bare fornuftig at skjell aksepterer samme område for funksjonene).

De fleste skjell bruker waitpid() og co. API for å hente utgangsstatusen, i så fall blir den avkortet til et tall mellom 0 og 255 når lagret i $?. Selv om du påkaller en funksjon involverer ikke gyting av en prosess og brukte waitpid() for å hente utgangsstatusen da alt er gjort i samme prosess, mange skjell etterligner også at waitpid() atferd når man påkaller funksjoner. Hvilket betyr at selv om du ringer return med en negativ verdi, vil $? inneholde et positivt tall.

Nå, blant de skjellene hvis return aksepterer negative tall (ksh88, ksh93, bash, zsh, pdksh og andre derivater enn mksh, yash), er det noen få ( pdksh og yash) som trenger det skrevet som return -- -123 som ellers at -123 blir tatt som tre -1, -2, -3 ugyldige alternativer.

Som pdksh og dens de rivativer (som OpenBSD sh eller posh) bevarer det negative tallet i $? at å gjøre return "$?" vil mislykkes når $? inneholder et negativt tall (som ville skje når kommandoen for siste kjøring var en funksjon som returnerte et negativt tall ).

return -- "$?" ville vært bedre i de skjellene. Vær imidlertid oppmerksom på at mens den støttes av de fleste skjell, er denne syntaksen ikke POSIX og i praksis ikke støttet av mksh og askerivater.

Så, for å oppsummere med pdksh-baserte skall, kan du bruke negative tall i argumenter for funksjoner, men hvis du gjør det, vil return "$@" ikke fungere. I andre skall, return "$@" fungerer, og du bør unngå å bruke negative tall (eller tall utenfor 0..255) som argumenter for return.

  • I alle skjell som jeg kjenner, vil ringing av return fra innsiden av en subshell som kjører inne i en funksjon, føre til at subshell avsluttes (med den angitte utgangsstatusen hvis noen eller den forrige kommandoen kjøre), men vil ellers ikke føre til at funksjonen returneres (for meg er det uklart om POSIX gir deg den garantien. Noen hevder at exit skal brukes i stedet for å avslutte subshells innvendige funksjoner). For eksempel

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

    vil sende ut:

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

    Ja, den implisitte returverdien til en funksjon er utgangsstatus for den siste kommando. Det gjelder også når som helst i et skallskript. Når som helst i sekvensen for skriptutførelse, er nåværende utgangsstatus utgangsstatus for den siste kommandoen. Selv kommando utført som en del av en variabel oppgave: var=$(exit 34). Forskjellen med funksjoner er at en funksjon kan endre utgangsstatus på slutten av utførelsen av funksjonen.

    Den alternative måten å endre «nåværende utgangsstatus» er å starte et underskall og avslutte det med eventuell nødvendig utgangsstatus:

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

    Og ja, utgangsstatus utvidelse må siteres:

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

    A (exit 34) fungerer også.
    Noen kan hevde at en mer robust konstruksjon skal være $(return 34), og at en exit bør «avslutte» skriptet som utføres. Men $(return 34) fungerer ikke med noen versjon av bash. Så den er ikke bærbar.

    Den sikreste måten å angi en utgangsstatus er å bruke den slik den ble designet for å fungere, definere og return fra en funksjon :

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

    Så, til slutt på en funksjon. det tilsvarer nøyaktig å ha enten ingenting eller return eller return "$?". Slutten av en funksjon trenger ikke å bety den «siste kodelinjen til en funksjon».

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

    Skrives ut:

    $ ./script foo 78 baz 89 baz 90 

    Den eneste praktiske bruken for "$?" er å enten skrive ut verdien: echo "$?" eller å lagre det i en variabel (da det er en kortvarig verdi og endring med hver kommando som utføres): exitstatus=$? (husk å sitere variabelen i kommandoer som export EXITSTATUS="$?".

    I return -kommandoen er det gyldige verdiområdet generelt 0 til 255, men forstå at verdiene til 126 + n brukes av noen skall for å signalisere spesiell utgangsstatus, så den generelle anbefalingen er å bruke 0-125.

    Legg igjen en kommentar

    Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *