Ich denke, die Empfehlung, die Sie gesehen haben, war für POSIX sh und / oder den testBefehl, der gleichzeitig als [Befehl fungiert, und nicht für das [[Konstrukt, das in ksh erschien (danke Stéphane Chazelas für den Tipp) und das auch zum Beispiel in bash, zsh und einigen anderen verwendet wird Muscheln.
In den meisten Sprachen wie C müssen die verbleibenden Teile je nach Operation nicht ausgewertet werden, wenn eine Klausel bereits als wahr oder falsch bekannt ist: Wenn wahr, nicht nach einer logischen oder nach ihr, wenn falsch, nicht nach einer logischen und , usw. Dies ermöglicht es beispielsweise, anzuhalten, wenn ein Zeiger NULL ist, und nicht zu versuchen, ihn in der nächsten Klausel zu dereferenzieren.
Aber sh ‚s - [ expr1 -o expr2 ]Konstrukt (einschließlich bash-Implementierung) tut dies nicht: Es wertet immer beiden Seiten, wenn man wollen würde nur ausdr1 ausgewertet werden. Dies wurde möglicherweise aus Gründen der Kompatibilität mit der testBefehlsimplementierung durchgeführt. Auf der anderen Seite folgen shs ||und &&do dem üblichen Prinzip: nicht bewertet, wenn es das Ergebnis nicht ändert.
Der zu beachtende Unterschied wäre also:
: > /tmp/effect #clear effect
if [ 1 -eq 1 -o $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
echo true;
fi
cat /tmp/effect
was ergibt:
true
or-was-evaluated
Oben [könnte jeder durch /usr/bin/[einen Alias für den testBefehl ersetzt worden sein, der zuvor [in Shells eingebaut wurde.
Während die beiden nächsten Konstrukte:
: > /tmp/effect #clear effect
if [ 1 -eq 1 ] || [ $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
echo true;
fi
cat /tmp/effect
oder
: > /tmp/effect #clear effect
if [[ 1 -eq 1 || $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]]; then
echo true;
fi
cat /tmp/effect
Wird nur nachgeben trueund effectleer lassen: ||verhält sich korrekt und hat auch [[dieses Problem behoben.
AKTUALISIEREN:
Wie @ StéphaneChazelas kommentierte, habe ich einige Unterschiede in Bezug auf die ursprüngliche Frage übersehen. Ich werde hier nur das Wichtigste (zumindest für mich) nennen: die Priorität der Betreiber.
Während die Shell keinen Vorrang hat:
if true || true && false; then
echo true
else
echo false
fi
Ausbeuten (weil es keinen Vorrang gibt und somit zuerst true || trueausgewertet wird und dann && false):
false
innerhalb [[ ]]des &&Operators hat Vorrang vor ||:
if [[ 1 -eq 1 || 1 -eq 1 && 1 -eq 0 ]]; then
echo true
else
echo false
fi
ergibt (weil 1 -eq 1 && 1 -eq 0gruppiert ist und somit das 2. Mitglied von ist ||):
true
Zumindest für ksh , bash , zsh .
Das [[ ]]Verhalten gegenüber [ ]logischen Shell-Operatoren und direkten Shell-Operatoren wurde verbessert .
[odertest( nicht[[) suchen Sie nach denOBTags (verknüpft mit der "veralteten" Definition) in der POSIX-Spezifikation fürtest. Intesteinigen pathologischen Fällen kann es unmöglich sein zu sagen, ob(oder)soll eine Syntax sein, die für den Testbefehl oder eine zu testende Zeichenfolge von Bedeutung ist. Daher können Personen, die die Veralterungsmarkierungen ignorieren und diese Syntax verwenden, tatsächlich das Gegenteil benötigen. veraltete"x$foo"Praxis; mit[[, das ist kein problem.