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

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'

あなたのせいで少し混乱していると思います。できるパイプを介してwhileループを入力します。私が何か間違っているのでしょうか、それともデザイン上の決定ですか?

ベストアンサー1

これは文法が定義された方法の結果にすぎません。 ~から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

おすすめ記事