Ř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
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ší odexit 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
aexit
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 sreturn
vs.exit(n)
, neboreturn
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 + globAbyste 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.
return
je, že pro funkce definované jakof() (...; 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, žecmd
byl zabit, když byl (většina shellů tyto informace stejně ‚ t získat nemůže.)sh
neboposh
), ‚ dreturn -- "$?"
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.return x
funguje jinak nežexit x
… jediné, co vím, je, žereturn x
neukončí aktuální proces.return
se používá k návratu z funkce nebo tečkového skriptu.exit
udělá něco úplně jiného (ukončí proces).