为什么不能反转 while 循环的输入重定向运算符的顺序?

phi*_*raj 11 bash io-redirection syntax

在 Bash 中,您可以将输入重定向操作符移到命令的前面:

cat <<< "hello"
# equivalent to
<<< "hello" cat
Run Code Online (Sandbox Code Playgroud)

为什么你不能对 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'
Run Code Online (Sandbox Code Playgroud)

我觉得这有点令人困惑,因为您可以通过管道进入 while 循环。我做错了什么还是只是一个设计决定?

mur*_*uru 16

这只是语法定义方式的结果。来自POSIX Shell 语法规范

command          : simple_command
                 | compound_command
                 | compound_command redirect_list
                 | function_definition
                 ;
Run Code Online (Sandbox Code Playgroud)

和:

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
                 ;
Run Code Online (Sandbox Code Playgroud)

如您所见,对于复合命令,重定向只允许在 之后,但对于简单命令,也允许在 之前。因此,当 shell 看到<redirection> foo,foo被视为简单命令,而不是复合命令,while不再被视为关键字:

$ < foo while
bash: while: command not found
Run Code Online (Sandbox Code Playgroud)

因此,这do是出乎意料的,因为它只允许在某些关键字之后。

所以这不仅适用于while循环,而且适用于使用保留字设置复合命令的大多数方法:

$ < foo {
bash: {: command not found
$ < foo if
bash: if: command not found
$ < foo for
bash: for: command not found
Run Code Online (Sandbox Code Playgroud)