Rozważ polecenia
eval false || echo ok
echo also ok
Zwykle spodziewalibyśmy się, że uruchomi to false
narzędzie, a ponieważ status wyjścia jest różny od zera, to wykonamy echo ok
i echo also ok
.
We wszystkich POSIX-jak muszli używam ( ksh93
, zsh
, bash
, dash
, OpenBSD ksh
, a yash
), to jest to, co się dzieje, ale robi się ciekawie, jeśli pozwalają set -e
.
Jeśli set -e
działa, OpenBSD sh
i ksh
powłoki (oba pochodzące z pdksh
) zakończą skrypt podczas wykonywania eval
. Żadna inna powłoka tego nie robi.
POSIX mówi, że błąd w specjalnym wbudowanym narzędziu (takim jak eval
) powinien spowodować zakończenie nieinteraktywnej powłoki. Nie jestem do końca pewien, czy wykonanie false
jest „błędem” (gdyby tak było, byłoby niezależne od set -e
bycia aktywnym).
Wydaje się, że sposobem obejścia tego jest umieszczenie eval
sub-powłoki,
( eval false ) || echo ok
echo also ok
Pytanie brzmi, czy mam to zrobić w poprawnym skrypcie powłoki POSIX-owym, czy też jest to błąd w powłoce OpenBSD? Co również oznacza „błąd” w tekście POSIX połączonym z powyższym?
Dodatkowy bit informacji: Powłoki OpenBSD wykonają echo ok
oba polecenia z lub bez set -e
polecenia
eval ! true || echo ok
Mój oryginalny kod wyglądał
set -e
if eval "$string"; then
echo ok
else
echo not ok
fi
które nie byłyby generowane not ok
przy string=false
użyciu powłok OpenBSD (to by się zakończyło), i nie byłem pewien, czy to z założenia, przez pomyłkę, przez nieporozumienie, czy coś innego.
eval false
generuje niezerowy status, więc spodziewałbymset -e
się, że w tym momencie zakończę skrypt. W przypadku!
set -e
nie ma zastosowania, ponieważ!
oświadczenie wyraźnie sprawdza status wyjścia.eval false
się zakończyć skrypt, nawet jeśli jest on częścią listy AND-OR lub instrukcji warunkowej? Nie zrobiłbym tego.set -e
jest ustawione, jeśli jest to prawidłowe zachowanie ... Zgadzam się, że sensowne jest, aby nie kończyć się instrukcją warunkową.set -e
więc `()` jest odpowiedzią.Odpowiedzi:
To, że żadna inna powłoka nie potrzebuje takiego obejścia, jest silnym sygnałem, że jest to błąd w ksh OpenBSD. W rzeczywistości ksh93 nie pokazuje takiego problemu.
To, że
||
w wierszu poleceń znajduje się znak, musi unikać wyjścia powłoki spowodowanego przez kod powrotu 1 po lewej stronie.Błąd specjalnego wbudowanego spowoduje wyjście z nieinteraktywnej powłoki zgodnie z POSIX, ale nie zawsze tak jest. Próba
continue
wyjścia z pętli jest błędem icontinue
jest wbudowana. Ale większość pocisków nie wychodzi po:Wbudowany, który emituje wyraźny błąd, ale nie wychodzi.
Tak więc wyjście włączone
false
jest generowane przezset -e
warunek, a nie przez wbudowaną charakterystykę polecenia (eval
w tym przypadku).Dokładne warunki
set -e
wyjścia, są bardziej rozmyte w POSIX.źródło
[przepraszam, jeśli to nie jest prawdziwa odpowiedź, zaktualizuję ją, kiedy do niej przejdę]
Rzuciłem okiem na kod źródłowy, a moje wnioski są następujące:
1) To błąd / ograniczenie, nic filozoficznego.
2) „Poprawka” z przenośnego rozwidlenia ksh (
mksh
) OpenBSD jest bardzo słaba, tylko pogarsza, bez naprawiania:Nowy błąd, inny niż wszystkie inne powłoki:
Wciąż nie naprawiony:
Można zastąpić
bash
powyżejdash
,zsh
,yash
,ksh93
, itd.źródło