Implicitní návrat do funkcí bash?

Řekněme, že mám takovou bash funkci:

gmx(){ echo "foo"; } 

bude tato funkce implicitně vrátit výstupní hodnotu příkazu echo nebo je nutné použít návrat?

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

Předpokládám, že cesta bash funguje, stav ukončení posledního příkazu funkce bash je ten, který se „vrátí“, ale není 100% jistý.

Odpovědět

return provede explicitní návrat z funkce shellu nebo„ dot script “(zdrojový skript). Pokud return není spuštěn, provede se implicitní návrat na konci funkce shellu nebo tečkového skriptu.

Pokud return se provádí bez parametru, je to ekvivalent návratu stavu ukončení naposledy provedeného příkazu.

Tak funguje return ve všech POSIXech skořápky.

Například

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

je tedy ekvivalentní

gmx () { echo "foo" return } 

což je stejné jako

gmx () { echo "foo" } 

Obecně je velmi vzácné použít $? vůbec. Je to opravdu nutné pouze v případě, že si ji potřebujete uložit pro budoucí použití, například pokud potřebujete několikrát prozkoumat její hodnotu (v takovém případě byste její hodnotu přiřadili proměnné a provedli na ní proměnnou řadu testů).

Komentáře

  • Nevýhodou použití return je, že pro funkce definované jako f() (...; cmd; return) brání optimalizaci, kterou provádí několik shellů při spouštění cmd ve stejném procesu jako subshell. U mnoha skořápek to také znamená, že stav ukončení funkce nenosí ‚ informace, že cmd byl zabit, když byl (většina shellů tyto informace stejně ‚ t získat nemůže.)
  • Pdksh a některé jeho deriváty (jako OpenBSD sh nebo posh), ‚ d return -- "$?" potřebujete šance, že posledním příkazem byla funkce, která vrátila záporné číslo. mksh (také na základě pdksh) zakazuje funkcím vracet záporné hodnoty.
  • díky, to pomáhá, myslím, že ne ‚ nechápu, jak return x funguje jinak než exit x … jediné, co vím, je, že return x neukončí aktuální proces.
  • @AlexanderMills No, ‚ je to, co jsem řekl: return se používá k návratu z funkce nebo tečkového skriptu. exit udělá něco úplně jiného (ukončí proces).
  • ano, to dává smysl, myslím, že to začínám lépe zvládat

Odpověď

Na stránce bash(1):

Po provedení je stav opuštění funkce stav opuštění posledního příkazu provedeného v těle.

Komentáře

  • správně a důsledkem může být, že příkaz return není nic jiného než stav ukončení?
  • Myslím, že return je integrovaný příkaz – i když return 1 se liší od exit 1 atd.
  • “ return [n]: Způsobí, že funkce přestane vykonávat a vrátí hodnotu určenou n volajícímu. Pokud je n vynecháno, návratový stav je stav posledního příkazu provedeného v těle funkce. “ (ibid) Takže return vynutí stav ukončení funkce na konkrétní hodnotu, pokud je uvedena.
  • @AlexandwrMills Ano, return a exit jsou obě integrované, kromě return lze použít pouze v rámci funkce. ‚ Skript nelze ukončit pomocí return. Stav ukončení je hodnota, kterou příkaz vrátí. return je příkaz, který vrací tuto hodnotu. Takže “ návratové prohlášení není nic jiného než stav ukončení “ prostě není úplně přesný. Jeden je hodnota, druhý příkaz plus hodnota.
  • @AlexanderMills, return se vrací z funkce, exit opustí celou skořápku. Je ‚ přesně stejný jako v, řekněme C s return vs. exit(n), nebo return vs. sys.exit() v Pythonu.

Odpověď

Do již poskytnutých odpovědí přidám pouze několik poznámek:

  • Přestože return má pro shell velmi zvláštní význam, z pohledu syntaxe se jedná o vestavěný příkaz prostředí a příkaz return je analyzován jako jakýkoli jiný jednoduchý příkaz. To tedy znamená, že stejně jako v argumentu jakéhokoli jiného příkazu, $?, pokud nebude uveden v uvozovkách, bude podléhat split + glob

    Abyste tomu zabránili, musíte to citovat $?:

    return "$?" 
  • return obvykle nepřijímá žádnou možnost (ksh93 „s přijímá obvyklé --help, --man, --author … ačkoli) Jediný argument, který očekává (volitelný), je návratový kód. Rozsah přijatých návratových kódů se liší od shellu k shellu a zda se nějaká hodnota mimo 0..255 správně projeví v

se také liší od prostředí k prostředí. Podrobnosti najdete v části Výchozí kód ukončení po ukončení procesu? .

Většina shellů přijímá záporná čísla (koneckonců argument předaný _exit() / exitgroup() systémové volání je int, takže s hodnotami přinejmenším – 2 31 až 2 31 -1, takže má smysl pouze to, že skořápky přijímají stejný rozsah pro své funkce).

Většina skořápek používá znak waitpid() a spol. API k načtení tohoto stavu ukončení, ale v takovém případě je zkráceno na číslo mezi 0 a 255, když je uloženo v $?. I když je vyvolána funkce nezahrnuje vytváření procesu a používá waitpid() k načtení jeho stavu ukončení, protože vše probíhá ve stejném procesu, mnoho skořápek také napodobuje, že waitpid() chování při vyvolání funkcí. Což znamená, že i když voláte return se zápornou hodnotou, $? bude obsahovat kladné číslo.

Nyní mezi těmi mušlemi, jejichž return přijímá záporná čísla (ksh88, ksh93, bash, zsh, pdksh a jiné deriváty než mksh, yash), existuje několik ( pdksh a yash), které je třeba zapsat jako return -- -123, jinak se -123 považuje za tři -1, -2, -3 neplatné možnosti.

Jako pdksh a jeho de soupeři (jako OpenBSD sh nebo posh) zachovají záporné číslo v $?, což znamená že provádění return "$?" by selhalo, když $? obsahuje záporné číslo (což by se stalo, kdyby příkazem posledního spuštění byla funkce, která vrátila záporné číslo ).

Takže return -- "$?" by v těchto skořápkách byl lepší. Mějte však na paměti, že i když je podporována většinou skořápek, tato syntaxe není POSIX a v praxi není podporována mksh a deriváty popela.

Takže, shrnu, s pdksh založené skořápky, můžete použít záporná čísla v argumentech funkcí, ale pokud tak učiníte, return "$@" nebude fungovat. V jiných skořápkách return "$@" bude fungovat a neměli byste používat záporná čísla (nebo čísla mimo 0..255) jako argumenty pro return.

  • Ve všech skořápkách, které znám, volání return z uvnitř subshellu běžícího uvnitř funkce způsobí ukončení subshell (s poskytnutým stavem ukončení, pokud existuje, nebo ten posledního příkazu běh), ale jinak nezpůsobí návrat z funkce (pro mě není jasné, zda vám POSIX poskytuje tuto záruku, někteří argumentují, že místo výstupních podsloupků by měl být použit exit vnitřní funkce). Například

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

    vygeneruje:

    still inside f. Exit status: 3 f exit status: 0 
  • Odpověď

    Ano, implicitní návratová hodnota funkce je stav ukončení posledního příkaz. To platí také v kterémkoli bodě libovolného skriptu prostředí. V kterémkoli bodě sekvence provádění skriptu je aktuální stav ukončení stav ukončení posledního provedeného příkazu. Dokonce i příkaz spuštěný jako součást přiřazení proměnné: var=$(exit 34). Rozdíl ve funkcích spočívá v tom, že funkce může změnit stav ukončení na konci provádění funkce.

    Alternativním způsobem, jak změnit „současný stav ukončení“, je spustit dílčí prostředí a ukončit jej pomocí jakýkoli potřebný stav ukončení:

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

    A ano, stav ukončení expanze je třeba uvést:

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

    A (exit 34) také funguje.
    Někteří mohou namítnout, že robustnější konstrukce by měla být $(return 34) a že exit by měl „ukončit“ prováděný skript. $(return 34) ale nefunguje s žádnou verzí bash. Není tedy přenosný.

    Nejbezpečnějším způsobem, jak nastavit stav ukončení, je použít jej tak, jak byl navržen pro práci, definování a return z funkce :

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

    Takže na konci funkce. je to přesně stejné jako mít nic nebo return nebo return "$?". Konec funkce nemusí znamenat „poslední řádek kódu funkce“.

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

    Vytiskne:

    $ ./script foo 78 baz 89 baz 90 

    Jediným praktickým použitím "$?" je buď vytisknout jeho hodnotu: echo "$?" nebo uložit je v proměnné (protože je to pomíjivá hodnota a mění se s každým provedeným příkazem): exitstatus=$? (nezapomeňte uvést proměnnou v příkazech jako export EXITSTATUS="$?".

    V příkazu return je platný rozsah hodnot obvykle 0 až 255, ale uvědomte si, že hodnoty 126 + n některé skořápky používají k signalizaci zvláštního stavu opuštění, takže obecné doporučení je použít 0-125.

    Napsat komentář

    Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *