输入重定向到 for 和 while

Sta*_*mar 4 bash shell-script shell-builtin

只是出于好奇,

此命令有效:

$ <file cat
Run Code Online (Sandbox Code Playgroud)

但这些都没有:

$ <file for
bash: for: command not found...

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

这是为什么?

ilk*_*chu 7

POSIX语法写的方式。命令定义为:

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
                 [...]

Run Code Online (Sandbox Code Playgroud)

和两者cmd_prefixcmd_suffix最终允许重定向。对于复合命令,只有redirect_list最后允许它们,没有任何东西允许它在前面。

它不完全具备是这样的,比如岩组接受这个就好了:

% > output for x in a b c ; do echo $x; done
% cat output 
a
b
c
Run Code Online (Sandbox Code Playgroud)

但这是 Zsh 不兼容的,因为在标准 shell 中,前导重定向强制for命令被解析为常规的简单命令,这意味着以下内容是有效的,并且 shell 将尝试查找并运行字面上调用的命令for(带有五个参数,以及标准输出重定向)。给出你看到的错误:

$ > output for x in a b c
bash: for: command not found
Run Code Online (Sandbox Code Playgroud)

(特别是在 Bash 中,首先解析整个输入行,因此如果您for-do-done将第一个示例中的整个 Bash放在一行中,它只会丢弃 的语法错误do,并且不会在此for之前执行。)

如果我不得不猜测,我希望定义的根本原因是它总是这样工作,所以标准已经这样编纂了它。

但请注意,已经讨论过在这方面更改标准。(可能没有人在他们的正常头脑中实际上依赖于> output for ...调用命令for而不是 shell 循环的含义)。

  • 另见 https://www.austingroupbugs.net/view.php?id=1276#c4509 (2认同)

Hau*_*ing 5

for并且while不是命令,它们是开始循环头的保留字。您可以在整个循环中使用重定向,但必须在最后。

这并不能正常工作:

<file for((i=0;i<3;i++)); do read line; echo "$line"; done
Run Code Online (Sandbox Code Playgroud)

确实有效:

      for((i=0;i<3;i++)); do read line; echo "$line"; done <file
Run Code Online (Sandbox Code Playgroud)

  • +1 重定向允许作为_simple command_的前缀或后缀,但不能作为复合命令(仅作为后缀)。 (2认同)