Come fare in modo che `local` acquisisca il codice di uscita?


11

Nel mio progetto ho il seguente frammento:

local output="$(bash "${1##*/}")"
echo "$?"

Questo stampa sempre zero a causa della localrimozione, tuttavia, localcomporta il $?comportamento corretto della variabile: che consiste nell'assumere il codice di uscita dalla subshell.

La mia domanda è: come posso mantenere locale questa variabile e catturare anche il valore di uscita?


1
shellchecknon solo risolverà questo problema, ma suggerirà la soluzione su unix.stackexchange.com/a/281749/24718 !
Waleed Khan,

Risposte:


16
#!/bin/bash
thing() {
   local foo=$(asjkdh) ret="$?"
   echo "$ret"
}

Questo farà eco 127, il codice di errore corretto per "comando non trovato".

È possibile utilizzare localper definire più di una variabile. Quindi creo anche la variabile locale RETper acquisire il codice di uscita della subshell prima che abbia esito localpositivo e venga impostato $?su zero.


È garantito che bashvaluta questa espressione da sinistra a destra?
Max Ried

Per quanto ne so, le assegnazioni di variabili sono in ordine, da sinistra a destra in questo contesto, sì.
DopeGhoti,

@MaxRiedito dal fatto che funziona in modo affidabile sembrerebbe indicare che sì, lo è. Tuttavia, non riesco a trovare informazioni al riguardo né dal POSIX né dal bashmanuale di riferimento.
cat

10
A parte questo, usare nomi di variabili in maiuscolo è una cattiva forma. Vedere le specifiche delle variabili di ambiente POSIX su pubs.opengroup.org/onlinepubs/009695399/basedefs/… , che descrivono i nomi in maiuscolo come riservati per le variabili con significato per la shell o il sistema e i nomi con almeno un carattere minuscolo riservato all'uso definito dall'applicazione, tenendo presente che le variabili di shell e le variabili di ambiente condividono uno spazio dei nomi (poiché, in caso di collisioni, l'assegnazione alla prima può avere la precedenza su quest'ultima).
Charles Duffy,

I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
terdon

27

Dichiarare la variabile locale prima di assegnarla:

thing() {
  local output
  output="$(bash "${1##*/}")"
  echo "$?"
}

A mio avviso, questo è anche più leggibile rispetto all'impostazione di una RETvariabile aggiuntiva . YMMV su questo, ma funziona esattamente come ci si aspetterebbe.


2
Questo è molto meglio dell'uso di una variabile separata, come dovrebbe essere ovvio se si desidera controllare il codice di ritorno di più incarichi: semplicemente local var1 var2 ...e Bob è tuo zio.
l0b0,

@ l0b0 Bob è mio zio. : D
cat
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.