Perché non è possibile invertire l'ordine dell'operatore di reindirizzamento di input per i cicli while?


11

In Bash è possibile spostare gli operatori di reindirizzamento di input nella parte anteriore di un comando:

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

Perché non riesci a fare lo stesso per i loop 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'

Lo trovo un po 'confuso dal momento che puoi convogliare in un ciclo while. Sto facendo qualcosa di sbagliato o è stata solo una decisione di progettazione?

Risposte:


16

È solo una conseguenza di come viene definita la grammatica. Dalla specifica POSIX Shell Grammar :

command          : simple_command
                 | compound_command
                 | compound_command redirect_list
                 | function_definition
                 ;

E:

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
                 ;

Come puoi vedere, con i comandi composti, il reindirizzamento è consentito solo dopo , ma con comandi semplici, è consentito anche prima. Quindi, quando la shell vede <redirection> foo, fooviene trattata come un semplice comando, non come un comando composto, e whilenon viene più trattata come una parola chiave:

$ < foo while
bash: while: command not found

Quindi, doè imprevisto, poiché è consentito solo dopo determinate parole chiave.

Quindi questo vale non solo per i whileloop, ma la maggior parte dei modi di impostare comandi composti usando parole riservate:

$ < foo {
bash: {: command not found
$ < foo if
bash: if: command not found
$ < foo for
bash: for: command not found

Bella spiegazione, grazie.
philraj,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.