Verhalten von „eval“ unter „set -e“ im bedingten Ausdruck

Verhalten von „eval“ unter „set -e“ im bedingten Ausdruck

Beachten Sie die Befehle

eval false || echo ok
echo also ok

Normalerweise würden wir erwarten, dass dadurch das falseDienstprogramm ausgeführt wird und, da der Beendigungsstatus ungleich Null ist, anschließend echo okund ausgeführt wird echo also ok.

Dies passiert in allen POSIX-ähnlichen Shells, die ich verwende ( ksh93, zsh, bash, dash, OpenBSD kshund ), aber es wird interessant, wenn wir aktivieren .yashset -e

Wenn set -eaktiv, beenden OpenBSDs shund kshShells (beide abgeleitet von ) das Skript bei der Ausführung von . Keine andere Shell macht das.pdksheval

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 -eob es aktiv ist).

Der Weg, dies zu umgehen, scheint darin zu bestehen, es evalin 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 okmit 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 okbei string=falseder 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, continueaus einer Schleife auszusteigen, ist ein Fehler und continueein 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 falsewird also durch die set -eBedingung und nicht durch die integrierte Eigenschaft des Befehls ( evalin diesem Fall) generiert.

Die genauen Bedingungen für den set -eAbbruch 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 bashdas oben genannte durch dash, zsh, yash, ksh93, usw. ersetzen.

verwandte Informationen