web-dev-qa-db-ja.com

whileループの入力リダイレクト演算子の順序を逆にできないのはなぜですか?

Bashでは、入力リダイレクト演算子をコマンドの前に移動できます。

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

なぜ同じことを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'

can whileループにパイプするので、少し混乱します。私は何か間違ったことをしていますか、それとも単なる設計上の決定でしたか?

11
philraj

文法がどのように定義されているかの結果です。 From POSIXシェル文法仕様

command          : simple_command
                 | compound_command
                 | compound_command redirect_list
                 | function_definition
                 ;

そして:

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
                 ;

ご覧のとおり、複合コマンドではリダイレクトはのみ許可されますが、単純なコマンドでは前にも許可されます。したがって、シェルが<redirection> fooを認識すると、fooは複合コマンドではなく単純なコマンドとして扱われ、whileはキーワードとして扱われなくなります。

$ < foo while
bash: while: command not found

したがって、doは特定のキーワードの後に​​のみ許可されるため、予期しないものです。

したがって、これはwhileループだけでなく、予約語を使用して複合コマンドを設定するほとんどの方法に当てはまります。

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