Warum bedeutet " wenn $(true) ; then ... fi` gelingen?

Inspiriert von diese Frage:

Was sollte eine if-Anweisung machen, wenn die Bedingung ist ein Kommando-substitution an dem der Befehl erzeugt keine Ausgabe?

HINWEIS: Das Beispiel ist if $(true); then ..., nicht if true ; then ...

Beispiel:

if $(true) ; then echo yes ; else echo no ; fi

Ich würde denken, dass $(true) sollte ersetzt werden durch die Ausgabe der true Befehl, das ist nichts. Es soll dann gleichwertig sein, entweder diese:

if "" ; then echo yes ; else echo no ; fi

dem Drucke no weil es keinen Befehl, dessen name ist ein leerer string, oder so:

if ; then echo yes ; else echo no ; fi

ist ein syntax-Fehler.

Aber das experiment zeigt, dass, wenn der Befehl erzeugt keine Ausgabe, die if - Anweisung behandelt es als wahr oder falsch in Abhängigkeit vom status des Befehls, sondern als dessen Ausgang.

Hier ist ein Skript, das zeigt das Verhalten:

#!/bin/bash

echo -n 'true:          ' ; if true          ; then echo yes ; else echo no ; fi
echo -n 'false:         ' ; if false         ; then echo yes ; else echo no ; fi
echo -n '$(echo true):  ' ; if $(echo true)  ; then echo yes ; else echo no ; fi
echo -n '$(echo false): ' ; if $(echo false) ; then echo yes ; else echo no ; fi
echo -n '$(true):       ' ; if $(true)       ; then echo yes ; else echo no ; fi
echo -n '$(false):      ' ; if $(false)      ; then echo yes ; else echo no ; fi
echo -n '"":            ' ; if ""            ; then echo yes ; else echo no ; fi
echo -n '(nothing):     ' ; if               ; then echo yes ; else echo no ; fi

und hier ist die Ausgabe die ich bekomme (Ubuntu 11.04, bash 4.2.8):

true:          yes
false:         no
$(echo true):  yes
$(echo false): no
$(true):       yes
$(false):      no
"":            ./foo.bash: line 9: : command not found
no
./foo.bash: line 10: syntax error near unexpected token `;'
./foo.bash: line 10: `echo -n '(nothing):     ' ; if               ; then echo yes ; else echo no ; fi'

Den ersten vier Zeilen Verhalten sich, als ich erwarten würde; die $(true) und $(false) Linien sind überraschend.

Weiteren experiment (hier nicht dargestellt) zeigt an, dass der Befehl zwischen $( und ) output erzeugt, dessen exit-status keinen Einfluss auf das Verhalten der if.

Sehe ich ein ähnliches Verhalten (aber verschiedene Fehlermeldungen in einigen Fällen) mit bash, ksh, zsh, ash, und dash.

Sehe ich nichts in der bash-Dokumentation, oder in der POSIX-Shell Command Language", Spezifikation, dies zu erklären.

(Oder vielleicht bin ich etwas fehlt offensichtlich.)

EDIT : Im Licht der akzeptierten Antwort, hier ist ein weiteres Beispiel für das Verhalten:

command='' ; if $command ; then echo yes ; else echo no ; fi

oder, was dasselbe ist:

command=   ; if $command ; then echo yes ; else echo no ; fi
  • Das ist sehr interessant. Wie auch immer, ich denke es ist ein Fehler in deiner Frage. Sie sagte, dass if "" ; then echo yes ; else echo no ; fi gibt keine, weil 'es ist kein Befehl, dessen name ist ein leerer string", aber durch die gleiche Logik sollte es zu einem Fehler, der so etwas wie "<leere Zeichenfolge>: Befehl nicht gefunden". Es gibt einige andere Unterschied zwischen if "" ; then echo yes ; else echo no ; fi und if "nonexistant" ; then echo yes ; else echo no ; fi
  • Ich denke, es gibt einen Fehler in Ihrem Kommentar. if "nonexistent" ; then … die Fehlermeldung erzeugt bash: nonexistent: command not found und dann sagt no. Durch Vergleich if "" ; then … die Fehlermeldung erzeugt bash: : command not found und dann sagt no. Das ist genau das gleiche Verhalten, außer nonexistent wurde gelöscht (d.h., ersetzt durch nichts). Es ist die gleiche Nachricht, die Sie erhalten, wenn Sie geben Sie nur "" (gefolgt von <Enter>). Können Sie uns ein Beispiel geben von einem Fall, wo die bash sagt so etwas wie <empty string> anstatt nur zu schreiben, eine leere Zeichenfolge? ... (Fortsetzung)
  • (Fortsetzung) ... Können Sie identifizieren die tatsächliche Differenz zwischen if "" ; then … und if "nonexistent" ; then …?
  • Ich bin damit einverstanden, dass dies eine interessante Frage. Mit all den erläuternden Beispielen vorgestellt auf dieser Seite, ich bin überrascht, dass niemand hat angeboten if "$(true)" ; then … und command='' ; if "$command" ; then … (mit Anführungszeichen), die das gleiche tun wie if "" ; then ….
Schreibe einen Kommentar