Epäsuora paluu bash-funktioissa?

Sano, että minulla on tällainen bash-toiminto:

gmx(){ echo "foo"; } 

tulee tämä toiminto implisiittisesti palauta echo -komennon poistumisarvo tai käyttääkö palautusta välttämätöntä?

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

Oletan, että tapa bash toimii, bash-funktion viimeisen komennon poistumistila on ”palautettu”, mutta ei 100% varma.

Vastaa

return palauttaa eksplisiittisen paluun kuoritoiminnosta tai” pisteohjelmasta ”(lähdekoodista). Jos return ei suoriteta, implisiittinen palautus tehdään shell-funktion tai pisteskriptin lopussa.

Jos return suoritetaan ilman parametria, se vastaa viimeksi suoritetun komennon poistumistilan palauttamista.

Näin return toimii kaikissa POSIX-tiedostoissa kuoret.

Esimerkiksi

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

vastaa siis

gmx () { echo "foo" return } 

mikä on sama kuin

gmx () { echo "foo" } 

Yleensä on hyvin harvoin, että sinun on käytettävä $? lainkaan. Sitä tarvitaan oikeastaan vain, jos sinun on tallennettava se myöhempää käyttöä varten, esimerkiksi jos sinun on tutkittava sen arvo useita kertoja (jolloin sinun tulisi määrittää sen arvo muuttujalle ja suorittaa useita testejä tälle muuttujalle). / p>

Kommentit

  • Yksi haittapuoli return -toiminnon käyttämisessä on se, että funktioille, jotka on määritelty kuten f() (...; cmd; return), se estää optimoinnin, jonka muutama kuori suorittaa cmd -toiminnon suorittamisessa samassa prosessissa kuin alikuori. Monien kuorien kanssa tämä tarkoittaa myös sitä, että funktion poistumistila ei sisällä ’ t, että cmd on tapettu, kun se on (Useimmat kuoret eivät ’ voi hakea kyseisiä tietoja joka tapauksessa).
  • Huomaa, että pdksh: llä ja joillakin sen johdannaisilla (kuten OpenBSD sh tai posh), ’ tarvitset return -- "$?" jos mahdollisuus, että viimeinen komento oli funktio, joka palautti negatiivisen luvun. mksh (perustuu myös pdksh: iin) kieltää funktioita palauttamasta negatiivisia arvoja.
  • kiitos, että tämä auttaa, luulen, että en ’ t ymmärtää kuinka return x toimii eri tavalla kuin exit x … ainoa mitä tiedän, on se, että return x ei poistu nykyisestä prosessista.
  • @AlexanderMills No, se ’ s mitä sanoin: return käytetään palaamaan funktiosta tai pisteohjelmasta. exit tekee jotain täysin erilaista (lopettaa prosessin).
  • joo, mikä on järkevää, luulen, että alaan saada parempi käsitys tästä

Vastaa

bash(1) -sivulta:

Suoritettaessa toiminnon poistumistila on viimeinen rungossa suoritetun komennon poistumistila.

Kommentit

  • oikein, ja seurauksena voi olla, että return-lause ei ole muuta kuin exit-tila?
  • Luulen, että return on sisäänrakennettu komento – vaikka return 1 on erilainen kuin exit 1 jne., Niin
  • ” return [n]: Aiheuttaa toiminnon suorittamisen lopettamisen ja palauttaa n: n määrittelemän arvon soittajalle. Jos n jätetään pois, palautustila on funktion rungossa viimeksi suoritetun komennon tila. ” (ibid) Joten, return pakottaa toiminnon poistumistilan tiettyyn arvoon, jos se on määritelty.
  • @AlexandwrMills Kyllä, return ja exit ovat molemmat sisäänrakennettuja, paitsi että return voidaan käyttää vain toiminnossa. Voit ’ t lopettaa komentosarjan return. Poistumistila on arvo, jonka komento palauttaa. return on komento, joka palauttaa arvon. Joten ” palautuslauseke ei ole muuta kuin poistumistila ” ei vain ole aivan tarkka. Yksi on arvo, toinen on komento plus-arvo.
  • @AlexanderMills, return palaa funktiosta, exit poistuu koko kuoresta. ’ on täsmälleen sama kuin paikassa, sano C sanalla return vs. exit(n), tai return vs. sys.exit() Pythonissa.

Vastaus

Lisän vain muutaman varovaisuuden huomautuksen jo annettuihin vastauksiin:

  • Vaikka return: llä on hyvin erityinen merkitys kuorelle, syntaksin kannalta se on sisäänrakennettu shell-komento ja return-lause jäsennetään kuten mikä tahansa muu yksinkertainen komento. Joten se tarkoittaa, että kuten minkä tahansa muun komennon argumentissa, $?, kun sitä ei ole mainittu, joutuisi jakamaan + glob: n

    Joten sinun on mainittava $? sen välttämiseksi:

    return "$?" 
  • return ei yleensä hyväksy mitään vaihtoehtoa (ksh93 ”s hyväksyy tavallisen --help, --man, --author … kuitenkin). Ainoa argumentti, jonka se odottaa (valinnainen), on palautuskoodi. Hyväksyttyjen palautuskoodien alue vaihtelee kuoresta kuoreen ja näkyykö arvon 0..255 ulkopuolella oleva arvo oikein kohdassa

vaihtelee myös kuoresta toiseen. Katso yksityiskohdat kohdasta Oletusarvoinen poistumiskoodi, kun prosessi lopetetaan? .

Useimmat kuoret hyväksyvät negatiiviset numerot (loppujen lopuksi argumentti välitetään _exit() / exitgroup() -järjestelmäkutsu on int, joten arvoilla, jotka sisältävät vähintään – 2 31 – 2 31 -1, joten on järkevää vain, että kuoret hyväksyvät toiminnoille saman alueen).

Useimmat kuoret käyttävät waitpid() ja yhdessä. Sovellusliittymä noutaakseen poistumistilan, mutta tällöin se katkaistaan luvuksi välillä 0–255, kun se on tallennettu kansioon $?. ei sisällä prosessin kutemista ja käytti waitpid() noutaakseen sen poistumistilan, koska kaikki tapahtuu samassa prosessissa, monet kuoret jäljittelevät myös sitä, että waitpid() käyttäytyminen funktioita kutsuttaessa. Tämä tarkoittaa, että vaikka soittaisit return negatiivisella arvolla, $? sisältää positiivisen luvun.

Niiden kuorien joukossa, joiden return hyväksyy negatiiviset luvut (ksh88, ksh93, bash, zsh, pdksh ja muut johdannaiset kuin mksh, yash), on muutama ( pdksh ja yash), jotka tarvitsevat sen kirjoitettuna nimellä return -- -123, muuten -123 otetaan kolmeksi -1, -2, -3 virheelliset vaihtoehdot.

Kuten pdksh ja sen de johdannaiset (kuten OpenBSD sh tai posh) säilyttävät negatiivisen luvun kohdassa $?, mikä tarkoittaa return "$?" -toiminnon tekeminen epäonnistuu, kun $? sisältää negatiivisen luvun (joka tapahtuisi, kun viimeinen ajo-komento oli funktio, joka palautti negatiivisen luvun ).

Joten return -- "$?" olisi parempi näissä kuorissa. Huomaa kuitenkin, että vaikka suurin osa kuoreista tukee tätä syntaksia, se ei ole POSIX ja käytännössä sitä ei tue mksh ja tuhkajohdannaiset.

Yhteenvetona, pdksh-pohjaisia kuoria, voit käyttää funktioiden argumenteissa negatiivisia lukuja, mutta jos teet niin, return "$@" ei toimi. Muissa kuorissa return "$@" toimii, ja sinun tulee välttää negatiivisten numeroiden (tai lukujen 0..255 ulkopuolella olevien lukujen) käyttöä argumentteina return.

  • Kaikissa tuntemissani kuoreissa return -sarjan kutsuminen toiminnon sisällä olevan alikuoren sisältä aiheuttaa alikuoren poistumisen (jos annettu tai jos viimeinen komento on poistumistila) run), mutta ei muuten aiheuta paluuta funktiosta (minulle on epäselvää, antaako POSIX sinulle kyseisen takuun, jotkut väittävät, että exit pitäisi käyttää exit-alikuorien sijaan sisäiset toiminnot). Esimerkiksi

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

    tuottaa:

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

    Kyllä, funktion implisiittinen palautusarvo on viimeksi suoritetun -tilan poistumistila -komento. Tämä pätee myös minkä tahansa shell-komentosarjan missä tahansa vaiheessa. Komentosarjan suoritusjakson missä tahansa vaiheessa nykyinen poistumistila on viimeksi suoritetun komennon poistumistila. Parillinen komento, joka suoritetaan osana muuttujamääritystä: var=$(exit 34). Ero funktioiden kanssa on se, että funktio voi muuttaa poistumistilaa toiminnon suorittamisen lopussa.

    Vaihtoehtoinen tapa muuttaa ”nykyinen poistumistila” on aloittaa alikuori ja lopettaa se tarvittava poistumistila:

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

    Ja kyllä, poistumistila laajennus on lainattava:

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

    Myös (exit 34) toimii.
    Jotkut saattavat väittää, että vankemman rakenteen tulisi olla $(return 34) ja että poistumisen pitäisi ”poistua” suoritettavasta komentosarjasta. Mutta $(return 34) ei toimi minkä tahansa -sovelluksen kanssa. Joten se ei ole kannettava.

    Turvallisin tapa asettaa poistumistila on käyttää sitä, koska se on suunniteltu toimimaan, määrittelemään ja return toiminnosta :

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

    Joten funktion lopussa. se vastaa täsmälleen sitä, että siinä ei ole mitään tai return tai return "$?". Funktion lopun ei tarvitse tarkoittaa ”funktion viimeistä koodiriviä”.

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

    Tulostaa:

    $ ./script foo 78 baz 89 baz 90 

    Ainoa käytäntö "$?" -sovelluksessa on joko tulostaa arvo: echo "$?" tai tallentaa se muuttujassa (koska se on lyhytaikainen arvo ja muuttuu jokaisen suoritettavan komennon yhteydessä): exitstatus=$? (muista mainita muuttuja komennoissa kuten export EXITSTATUS="$?".

    return -komennossa kelvollinen arvoalue on yleensä 0 – 255, mutta ymmärrä, että 126 + n käytetään joissakin simpukoissa merkitsemään erityistä poistumistilaa, joten yleinen suositus on 0-125.

    Vastaa

    Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *