Beachten Sie die Befehle
eval false || echo ok
echo also ok
Normalerweise würden wir erwarten, dass dadurch das false
Dienstprogramm ausgeführt wird und, da der Beendigungsstatus ungleich Null ist, anschließend echo ok
und ausgeführt wird echo also ok
.
Dies passiert in allen POSIX-ähnlichen Shells, die ich verwende ( ksh93
, zsh
, bash
, dash
, OpenBSD ksh
und ), aber es wird interessant, wenn wir aktivieren .yash
set -e
Wenn set -e
aktiv, beenden OpenBSDs sh
und ksh
Shells (beide abgeleitet von ) das Skript bei der Ausführung von . Keine andere Shell macht das.pdksh
eval
POSIX sagtdass ein Fehler in einem speziellen integrierten Dienstprogramm (wie eval
) dazu führen sollte, dass die nicht interaktive Shell beendet wird. Ich bin nicht ganz sicher, ob die Ausführung false
„einen Fehler“ darstellt (wenn ja, wäre dies unabhängig davon, set -e
ob es aktiv ist).
Der Weg, dies zu umgehen, scheint darin zu bestehen, es eval
in eine Unter-Shell zu setzen,
( eval false ) || echo ok
echo also ok
Die Frage ist, ob ich das in einem POSIX-korrekten Shell-Skript tun muss oder ob es sich um einen Fehler in der OpenBSD-Shell handelt. Und was ist mit „Fehler“ im oben verlinkten POSIX-Text gemeint?
Zusätzliche Information: Die OpenBSD-Shells führen die Befehle sowohl echo ok
mit als auch ohne aus.set -e
eval ! true || echo ok
Mein ursprünglicher Code sah so aus
set -e
if eval "$string"; then
echo ok
else
echo not ok
fi
was würdenichtAusgabe not ok
bei string=false
der Verwendung der OpenBSD-Shells (es würde beendet werden) und ich war nicht sicher, ob dies Absicht, ein Fehler, ein Missverständnis oder etwas anderes war.
Antwort1
Dass keine andere Shell einen solchen Workaround benötigt, ist ein starker Hinweis darauf, dass es sich um einen Fehler in OpenBSD ksh handelt. Tatsächlich tritt dieses Problem bei ksh93 nicht auf.
Das Vorhandensein eines ||
in der Befehlszeile muss das Beenden der Shell verhindern, das durch einen Rückgabecode von 1 auf der linken Seite verursacht wird.
Der Fehler einesbesonderseingebaut soll das Beenden einer nicht interaktiven Shell bewirkengemäß POSIXaber das ist nicht immer der Fall. Der Versuch, continue
aus einer Schleife auszusteigen, ist ein Fehler und continue
ein eingebauter Fehler. Aber die meisten Shells werden nicht beendet, wenn:
continue 3
Ein integriertes Programm, das einen eindeutigen Fehler ausgibt, aber nicht beendet wird.
Der Ausgang false
wird also durch die set -e
Bedingung und nicht durch die integrierte Eigenschaft des Befehls ( eval
in diesem Fall) generiert.
Die genauen Bedingungen für den set -e
Abbruch sind bei POSIX deutlich unklarer.
Antwort2
[Entschuldigung, wenn das keine richtige Antwort ist, ich werde sie aktualisieren, wenn ich dazu komme]
Ich habe mir den Quellcode angesehen und bin zu folgenden Schlussfolgerungen gekommen:
1) Es handelt sich um einen Fehler/eine Einschränkung, dahinter steckt nichts Philosophisches.
2) Der "Fix" dafür aus dem portablen Fork von OpenBSDs ksh ( mksh
) istsehrarm, macht die Dinge nur schlimmer, ohne sie wirklich zu beheben:
Neuer Fehler, anders als bei allen anderen Shells:
mksh -ec 'eval "false; echo yup"'
yup
bash -ec 'eval "false; echo yup"'
(nothing)
Immer noch nicht wirklich behoben:
mksh -ec 'eval "set -e; false" || echo yup'
(nothing)
bash -ec 'eval "set -e; false" || echo yup'
yup
Sie können bash
das oben genannte durch dash
, zsh
, yash
, ksh93
, usw. ersetzen.