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?

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

Belle explication, merci.
philraj
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.