Pourquoi ne pouvez-vous pas inverser l'ordre de l'opérateur de redirection d'entrée pour les boucles while?

11

Dans Bash, vous pouvez déplacer les opérateurs de redirection d'entrée vers l'avant d'une commande:

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

Pourquoi n'êtes-vous pas en mesure de faire de même pour les boucles while?

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'

Je trouve cela un peu déroutant car vous pouvez diriger dans une boucle while. Suis-je en train de faire quelque chose de mal ou était-ce simplement une décision de conception?

philraj
la source

Réponses:

16

C'est juste une conséquence de la façon dont la grammaire est définie. De la spécification POSIX Shell Grammar :

command          : simple_command
                 | compound_command
                 | compound_command redirect_list
                 | function_definition
                 ;

Et:

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
                 ;

Comme vous pouvez le voir, avec les commandes composées, la redirection n'est autorisée qu'après , mais avec les commandes simples, elle est également autorisée avant. Ainsi, lorsque le shell voit <redirection> foo, fooest traité comme une commande simple, pas une commande composée, et whilen'est plus traité comme un mot-clé:

$ < foo while
bash: while: command not found

Par conséquent, le doest inattendu, car il n'est autorisé qu'après certains mots clés.

Cela s'applique donc non seulement aux whileboucles, mais à la plupart des façons de configurer des commandes composées à l'aide de mots réservés:

$ < foo {
bash: {: command not found
$ < foo if
bash: if: command not found
$ < foo for
bash: for: command not found
muru
la source
Belle explication, merci.
philraj