Warum können Sie die Reihenfolge des Eingabeumleitungsoperators für while-Schleifen nicht umkehren?

11

In Bash können Sie Eingabeumleitungsoperatoren an die Vorderseite eines Befehls verschieben:

cat <<< "hello"
# equivalent to
<<< "hello" cat

Warum können Sie das nicht für while-Schleifen tun?

while read -r line; do echo "$line"; done <<< "hello"
# hello

<<< "hello" while read -r line; do echo "$line"; done
# -bash: syntax error near unexpected token `do'

Ich finde es ein bisschen verwirrend , da Sie können Rohr in einer while - Schleife. Mache ich etwas falsch oder war es nur eine Designentscheidung?

Philraj
quelle

Antworten:

16

Es ist nur eine Folge der Definition der Grammatik. Aus der POSIX Shell-Grammatikspezifikation :

command          : simple_command
                 | compound_command
                 | compound_command redirect_list
                 | function_definition
                 ;

Und:

simple_command   : cmd_prefix cmd_word cmd_suffix
                 | cmd_prefix cmd_word
                 | cmd_prefix
                 | cmd_name cmd_suffix
                 | cmd_name
                 ;
[...]
cmd_prefix       :            io_redirect
                 | cmd_prefix io_redirect
                 |            ASSIGNMENT_WORD
                 | cmd_prefix ASSIGNMENT_WORD
                 ;
cmd_suffix       :            io_redirect
                 | cmd_suffix io_redirect
                 |            WORD
                 | cmd_suffix WORD
                 ;

Wie Sie sehen können, ist bei zusammengesetzten Befehlen die Umleitung nur nachher zulässig , bei einfachen Befehlen jedoch auch vorher. Wenn die Shell sieht <redirection> foo, foowird sie als einfacher Befehl und nicht als zusammengesetzter Befehl whilebehandelt und nicht mehr als Schlüsselwort:

$ < foo while
bash: while: command not found

Daher ist das dounerwartet, da es nur nach bestimmten Schlüsselwörtern erlaubt ist.

Dies gilt also nicht nur für whileSchleifen, sondern für die meisten Möglichkeiten, zusammengesetzte Befehle mit reservierten Wörtern einzurichten:

$ < foo {
bash: {: command not found
$ < foo if
bash: if: command not found
$ < foo for
bash: for: command not found
muru
quelle
Schöne Erklärung, danke.
Philraj