Wie kann `local` den Exit-Code erfassen?

11

In meinem Projekt habe ich folgenden Ausschnitt:

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

Dies gibt immer Null aus local, da das Entfernen jedoch dazu führt, localdass sich die $?Variable korrekt verhält: Dies bedeutet , dass der Exit-Code aus der Subshell übernommen wird.

Meine Frage ist: Wie kann ich diese Variable lokal halten und gleichzeitig den Exit-Wert erfassen?

Ultimativer Falke
quelle
1
shellcheckwird dieses Problem nicht nur beheben, sondern die Lösung auch unter unix.stackexchange.com/a/281749/24718 vorschlagen !
Waleed Khan

Antworten:

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

Dies gibt 127den korrekten Fehlercode für "Befehl nicht gefunden" wieder.

Sie können localmehr als eine Variable definieren. Also erstelle ich einfach auch die lokale Variable RET, um den Exit-Code der Subshell zu erfassen, bevor dies localerfolgreich ist und $?auf Null gesetzt wird.

DopeGhoti
quelle
Ist garantiert, dass bashdieser Ausdruck von links nach rechts ausgewertet wird?
Max Ried
Soweit mir bekannt ist, sind die Variablenzuordnungen in diesem Zusammenhang von links nach rechts in Ordnung, ja.
DopeGhoti
@MaxRied die Tatsache, dass dies zuverlässig funktioniert, scheint darauf hinzudeuten, dass ja, es ist. Ich kann jedoch weder aus POSIX noch aus bashdem Referenzhandbuch Informationen dazu finden .
Katze
10
Abgesehen davon ist die Verwendung von All-Caps-Variablennamen eine schlechte Form. Weitere Informationen finden Sie in der POSIX-Umgebungsvariablenspezifikation unter pubs.opengroup.org/onlinepubs/009695399/basedefs/… , in der alle Großbuchstaben als für Variablen mit Bedeutung für die Shell oder das System reserviert und Namen mit mindestens einem Kleinbuchstaben beschrieben werden reserviert für die anwendungsdefinierte Verwendung, wobei zu berücksichtigen ist, dass Shell-Variablen und Umgebungsvariablen einen gemeinsamen Namespace haben (da bei Kollisionen die Zuweisung zu ersteren den letzteren überschreiben kann).
Charles Duffy
Kommentare sind nicht für eine ausführliche Diskussion gedacht. Dieses Gespräch wurde in den Chat verschoben .
Terdon
27

Deklarieren Sie die lokale Variable, bevor Sie sie zuweisen:

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

Meiner Meinung nach ist dies auch besser lesbar als das Setzen einer zusätzlichen RETVariablen. YMMV darauf, aber es funktioniert genau so, wie Sie es erwarten würden.

Platzhalter
quelle
2
Dies ist viel besser als die Verwendung einer separaten Variablen. Dies sollte offensichtlich sein, wenn Sie den Rückkehrcode mehrerer Zuweisungen überprüfen möchten: einfach local var1 var2 ...und Bob ist Ihr Onkel.
10b0
@ l0b0 Bob ist mein Onkel. : D
Katze