在 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 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> 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