Bash 手册说
Run Code Online (Sandbox Code Playgroud){ list; }将命令列表放在大括号之间会导致列表在当前 shell 上下文中执行。没有创建子shell。以下列表中的分号(或换行符)是必需的。
大括号是保留字,因此必须用空格或其他 shell 元字符将它们与列表分开。
括号是运算符,即使它们没有通过空格与列表分开,也会被 shell 识别为单独的标记。
如果我删除分号,如下所示:
$ { date }
>
Run Code Online (Sandbox Code Playgroud)
为什么它需要 stdin 输入?
元字符是分隔单词的字符。分号和空格都是“shell 元字符”。为什么空格不能分隔单词date和}?为什么我们需要分号而不是空格来分隔单词?
它在等待关闭}。您已经输入了一个包含一个命令、date }和一个换行符的列表,因此您仍然在命令组中,并且可以向列表中添加另一个命令或终止它。
所以它不是在等待标准输入(确切地说),而是在等待你完成你在第一行开始的命令。如果你}在这里输入,你(可能)会从date命令中得到一个错误,说它不理解“ }”。
{和}是有效的参数常用命令,如在点1所示。例如,find使用{}作为参数。
具体来说,只有“ {”和“ }”才是保留字。shell 中的保留字仅在它们完全作为自己的整个单词给出时才重要,并且仅在它们被特别期望的地方才有意义。他们期望的最重要的地方是在命令的开头。
分号或换行符表示出}现在列表中下一个命令的开头,可以将其识别为保留字并给予特殊处理。这是由 POSIX 为 shell 语法指定的:
该规则还暗示,除了在输入中的某些位置(例如 a
<newline>或<semicolon>;之后)之外,不会识别保留字。语法假定如果保留字是有意的,则由用户正确分隔
如果另一个保留词“then”不能用作普通词,那会很烦人,所以这基本上是有道理的。(和),相比之下,是运算符,可以出现在任何地方,如果它们用于其文字值,则需要进行转义。这本质上是一个历史人工制品,如果重做,可能会在一个方向或另一个方向做出更一致的选择,或者可能会要求使用更复杂的解析器。
特别是对于 Bash,命令分组的大括号也需要与大括号扩展的大括号区分开来,解析器假设您不太可能对以空格开头的命令进行大括号扩展。
可以选择是否保持特殊情况的历史兼容性,而其他一些 shell,例如 zsh,具有更聪明的解析器并且能够处理{ date }您想要的含义。