Jak sprawić, by `local` przechwycił kod wyjścia?


11

W moim projekcie mam następujący fragment kodu:

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

To zawsze wypisuje zero local, ponieważ usunięcie localpowoduje jednak, że $?zmienna zachowuje się poprawnie: co oznacza przyjęcie kodu wyjścia z podpowłoki.

Moje pytanie brzmi: jak mogę zachować tę zmienną lokalnie, jednocześnie rejestrując wartość wyjściową?


1
shellchecknie tylko złapie ten problem, ale zaproponuje rozwiązanie na unix.stackexchange.com/a/281749/24718 !
Waleed Khan,

Odpowiedzi:


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

Spowoduje to wyświetlenie echa 127, poprawnego kodu błędu dla „polecenia nie znaleziono”.

Możesz użyć localdo zdefiniowania więcej niż jednej zmiennej. Więc po prostu tworzę również zmienną lokalną, RETaby przechwycić kod wyjściowy podpowłoki, zanim się localpowiedzie i ustawi się $?na zero.


Czy jest gwarantowane, że bashocenia to wyrażenie od lewej do prawej?
Max zmarł

O ile mi wiadomo, przypisania zmiennych są w porządku, od lewej do prawej w tym kontekście, tak.
DopeGhoti

@Max Wiedział, że to działa niezawodnie, wydaje się wskazywać, że tak. Nie mogę jednak znaleźć żadnych informacji na ten temat ani w POSIX, ani w bashpodręczniku użytkownika.
kot

10
Nawiasem mówiąc, używanie nazw zmiennych wielkimi literami jest złą formą. Zobacz specyfikację zmiennych środowiskowych POSIX na pubs.opengroup.org/onlinepubs/009695399/basedefs/... , która opisuje nazwy pisane wielkimi literami jako zastrzeżone dla zmiennych mających znaczenie dla powłoki lub systemu oraz nazwy zawierające co najmniej jedną małą literę zarezerwowane do użytku zdefiniowanego przez aplikację, pamiętając, że zmienne powłoki i zmienne środowiskowe mają wspólną przestrzeń nazw (ponieważ w przypadku kolizji przypisanie do pierwszej może zastąpić drugą).
Charles Duffy,

Komentarze nie są przeznaczone do rozszerzonej dyskusji; ta rozmowa została przeniesiona do czatu .
terdon

27

Zadeklaruj zmienną lokalną przed przypisaniem jej:

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

Moim zdaniem jest to również bardziej czytelne niż ustawienie dodatkowej RETzmiennej. YMMV, ale działa tak, jak można się spodziewać.


2
Jest to o wiele lepsze niż używanie oddzielnej zmiennej, co powinno być oczywiste, jeśli chcesz sprawdzić kod powrotu wielu zadań: po prostu local var1 var2 ...i Bob jest twoim wujem.
l0b0

@ l0b0 Bob jest moim wujem. : D
kot
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.