Întoarcerea implicită a funcțiilor bash?

Spune că am o funcție bash așa:

gmx(){ echo "foo"; } 

această funcție implicit returnează valoarea de ieșire a comenzii echo sau este necesară returnarea?

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

Presupun că bash funcționează, starea de ieșire a comenzii finale a funcției bash este cea care este „returnată”, dar nu 100% sigură.

Răspuns

return revine explicit dintr-o funcție shell sau„ dot script ”(un script sursat). Dacă return nu este executat, se face o returnare implicită la sfârșitul funcției shell sau a scriptului punct.

Dacă return este executat fără parametru, este echivalent cu returnarea stării de ieșire a celei mai recente comenzi executate.

Așa funcționează return în toate POSIX cochilii.

De exemplu,

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

este, prin urmare, echivalent cu

gmx () { echo "foo" return } 

care este la fel ca

gmx () { echo "foo" } 

În general, este foarte rar să utilizați $? deloc. Este într-adevăr necesar numai dacă trebuie să-l salvați pentru utilizare ulterioară, de exemplu dacă trebuie să investigați valoarea acesteia de mai multe ori (caz în care ați atribui valoarea acesteia unei variabile și efectuați o serie de teste pe acea variabilă) / p>

Comentarii

  • Un dezavantaj al utilizării return este acela pentru funcțiile definite ca f() (...; cmd; return), împiedică optimizarea pe care o fac câteva shell-uri pentru a rula cmd în același proces ca subshell-ul. Cu multe shell-uri, asta înseamnă, de asemenea, că starea de ieșire a funcției nu ‘ nu poartă informația că cmd a fost ucis când a fost (majoritatea shell-urilor nu pot ‘ oricum să preia aceste informații).
  • Rețineți că, cu pdksh și unele dintre derivatele sale (cum ar fi OpenBSD sh sau posh), aveți nevoie ‘ de return -- "$?" dacă a existat un șansa ca ultima comandă să fie o funcție care a returnat un număr negativ. mksh (bazat și pe pdksh) interzice funcțiilor să returneze valori negative.
  • mulțumesc că ajută, cred că nu ‘ nu înțeleg cum funcționează diferit return x decât exit x … singurul lucru pe care îl știu este că return x nu va ieși din procesul curent.
  • @AlexanderMills Ei bine, ‘ este ceea ce am spus: return este folosit pentru a reveni dintr-o funcție sau un script punct. exit face ceva complet diferit (încheie un proces).
  • da, asta are sens, cred că încep să mă descurc mai bine cu acest lucru

Răspuns

Din bash(1) pagina manuală:

Când este executată, starea de ieșire a unei funcții este starea de ieșire a ultimei comenzi executate în corp.

Comentarii

  • corect, și un corolar ar putea fi că declarația return nu este altceva decât starea de ieșire?
  • Cred că return este o comandă încorporată – deși return 1 este diferit de exit 1, așa că
  • ” return [n]: determină oprirea executării unei funcții și returnarea valorii specificate de n către apelantul său. Dacă n este omis, starea de returnare este cea a ultimei comenzi executate în corpul funcției. ” (ibid) Deci, return forțează starea de ieșire a unei funcții la o anumită valoare, dacă este specificat.
  • @AlexandwrMills Da, return și exit sunt ambele încorporate, cu excepția faptului că return poate fi utilizat numai în cadrul funcției. Nu puteți ‘ t finaliza un script cu return. Starea de ieșire este valoarea pe care o returnează comanda. return este o comandă care returnează acea valoare. Deci, ” declarația de returnare nu este altceva decât starea de ieșire ” pur și simplu nu este destul de precisă. Una este o valoare, cealaltă este comanda plus valoare.
  • @AlexanderMills, return revine din funcție, exit iese din întreaga coajă. ‘ este exact la fel ca în, să spunem C cu return vs. exit(n), sau return vs. sys.exit() în Python.

Răspuns

Voi adăuga doar câteva note de precauție la răspunsurile deja furnizate:

  • Chiar dacă return are o semnificație foarte specială pentru shell, din punct de vedere al sintaxei, este o comandă integrată a shell-ului și o instrucțiune return este analizat ca orice altă comandă simplă. Deci, asta înseamnă că, la fel ca în argumentul oricărei alte comenzi, $? atunci când nu este citat, ar fi supus divizării + glob

    Deci, trebuie să citați $? pentru a o evita:

    return "$?" 
  • return de obicei nu acceptă nicio opțiune (ksh93 „s acceptă --help obișnuit, --man, --author … totuși) Singurul argument pe care îl așteaptă (opțional) este codul de returnare. Gama de coduri de returnare acceptate variază de la shell la shell și dacă vreo valoare în afara de 0..255 este reflectată corect în

variază, de asemenea, de la coajă la coajă. Consultați Cod de ieșire implicit când procesul este încheiat? pentru detalii despre acest lucru.

Majoritatea shell-urilor acceptă numere negative (la urma urmei, argumentul a fost apelul de sistem _exit() / exitgroup() este un int, deci cu valori care să cuprindă cel puțin – 2 31 la 2 31 -1, deci are sens doar că shell-urile acceptă același interval pentru funcțiile sale).

Majoritatea shell-urilor utilizează waitpid() și co. API pentru a prelua starea de ieșire, cu toate acestea, caz în care, este „trunchiat la un număr între 0 și 255 când stocat în $?. Chiar dacă invocă o funcție nu implică apariția unui proces și folosit waitpid() pentru a-și recupera starea de ieșire, deoarece totul se face în același proces, multe cochilii imită, de asemenea, că waitpid() comportament atunci când invocați funcții. Ceea ce înseamnă că, chiar dacă apelați return cu o valoare negativă, $? va conține un număr pozitiv.

Acum, printre acele shell-uri al căror return acceptă numere negative (ksh88, ksh93, bash, zsh, pdksh și alte derivate decât mksh, yash), există câteva ( pdksh și yash) care au nevoie de el scris ca return -- -123 altfel că -123 este luat ca trei -1, -2, -3 opțiuni nevalide.

Ca pdksh și de rivative (cum ar fi OpenBSD sh sau posh) păstrează numărul negativ din $?, ceea ce înseamnă că a face return "$?" ar eșua atunci când $? conține un număr negativ (ceea ce s-ar întâmpla când ultima comandă de rulare a fost o funcție care a returnat un număr negativ ).

Deci, return -- "$?" ar fi mai bun în acele cochilii. Cu toate acestea, rețineți că, deși este susținut de majoritatea shell-urilor, această sintaxă nu este POSIX și, în practică, nu este susținută de mksh și de derivați de cenușă.

Deci, pentru a rezuma, cu shell-uri bazate pe pdksh, puteți utiliza numere negative în argumentele funcțiilor, dar dacă da, return "$@" nu va funcționa. În alte shell-uri, return "$@" va funcționa și ar trebui să evitați utilizarea numerelor negative (sau numere în afara de 0..255) ca argumente pentru return.

  • În toate shell-urile pe care le știu, apelarea return din interiorul unui subshell care rulează în interiorul unei funcții va provoca ieșirea subshell-ului (cu starea de ieșire furnizată dacă există sau cea a ultimei comenzi run), dar altfel nu va provoca o revenire de la funcție (pentru mine, nu este clar dacă POSIX vă oferă acea garanție, unii susțin că exit ar trebui să fie folosit în loc de exit subshells funcții interne). De exemplu,

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

    va genera:

    still inside f. Exit status: 3 f exit status: 0 
  • Răspuns

    Da, valoarea de returnare implicită a unei funcții este starea de ieșire a ultimului executat Comanda . Acest lucru este valabil și în orice moment al oricărui script shell. În orice moment al secvenței de execuție a scriptului, starea actuală de ieșire este starea de ieșire a ultimei comenzi executate. Chiar și comanda executată ca parte a unei atribuiri variabile: var=$(exit 34). Diferența cu funcțiile este că o funcție ar putea modifica starea de ieșire la sfârșitul executării funcției.

    Modalitatea alternativă de a schimba „starea de ieșire actuală” este de a porni un sub shell și de a-l ieși cu orice stare de ieșire necesară:

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

    Și da, starea de ieșire expansiune trebuie să fie citat:

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

    Un (exit 34) funcționează și el.
    Unii ar putea susține că o construcție mai robustă ar trebui să fie $(return 34) și că o ieșire ar trebui să „părăsească” scriptul care se execută. Dar $(return 34) nu funcționează cu nicio versiune a bash. Deci, nu este portabil.

    Cel mai sigur mod de a seta o stare de ieșire este să-l utilizați așa cum a fost conceput pentru a funcționa, defini și return dintr-o funcție :

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

    Deci, la sfârșitul unei funcții. este exact echivalent să nu ai nimic sau return sau return "$?". Sfârșitul unei funcții nu trebuie să însemne „ultima linie de cod a unei funcții”.

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

    Se va imprima:

    $ ./script foo 78 baz 89 baz 90 

    Singura utilizare practică pentru "$?" este fie să tipăriți valoarea: echo "$?", fie să stocați o într-o variabilă (deoarece este o valoare efemeră și se schimbă cu fiecare comandă executată): exitstatus=$? (nu uitați să citiți variabila în comenzi precum export EXITSTATUS="$?".

    În comanda return, intervalul valid de valori este în general de la 0 la 255, dar înțelegeți că valorile 126 + n sunt utilizate de unele shell-uri pentru a semnaliza starea de ieșire specială, așadar, recomandarea generală este să folosiți 0-125.

    Lasă un răspuns

    Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *