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


11

在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循环。我是在做错什么还是仅仅是设计决定?

Answers:


16

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

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
                 ;

如您所见,对于复合命令,仅在之后允许重定向,而对于简单命令,也允许在之前重定向。因此,当shell看到时<redirection> foofoo被视为简单命令,而不是复合命令,并且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

很好的解释,谢谢。
philraj
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.