TL; DR:为什么POSIX大括号组在{
保留字之后需要空格,但是在保留字之后不需要subshell (
?
POSIX Shell语法定义了括号组和子shell,如下所示
brace_group : Lbrace compound_list Rbrace
subshell : '(' compound_list ')'
现在,如果从字面上看,空格是很重要的。这将意味着必须有空间来描述开括号和闭括号以及括号,如
{ echo hello world; }
( echo hello world )
这也将与“ 复合命令”定义保持一致:
这些复合命令中的每一个在开头都有一个保留字或控制运算符,在结尾处有一个对应的终止符保留字或运算符。
但是,没有意义的是为什么(list)
并且可以( list )
正常工作((
不需要后面的空格),但是括号扩展必须有一个前导空格,即{echo hello;}
不起作用。
当然,保留字被视为空壳字会有意义,之后需要一个空格以与字段拆分的概念保持一致,但是定义本身并未提及空格。此外,如果POSIX的复合命令定义都将{
和(
都视为保留字,那么为什么在这些保留字之后的空格字符方面会有不同的对待?现在,ksh(1)手册确实指出:
单词是字符序列,由无引号的空格字符(空格,制表符和换行符)或元字符(<,>,|,;,&,(和))定界
换句话说,有意义的是ksh将被识别(
为单词定界符,其中第一个单词将是命令或变量赋值。POSIX,但是似乎没有提到(
元字符。就POSIX语法而言,我发现的唯一可能的解释是{
被认为是“令牌”,此处(
未列出为一个。
/* These are reserved words, not operator tokens, and are
recognized when reserved words are recognized. */
%token Lbrace Rbrace Bang
/* '{' '}' '!' */
那么,这种差异的确切原因是什么?
接受的答案注释:
将接受的复选标记移到Isaac的答案,因为它提供了标准形式,可以直接解决我的问题:
例如,'('和')'是控制运算符,因此
<space>
(list)中不需要。但是,“ {”和“}”是{list;}中的保留字,因此在这种情况下,前导<space>
和<semicolon>
是必需的。接受Kusalananda的回答。库萨兰南达的答案满足了我的需求,尽管主要是从非正式和直观的角度来看。它指出{
是保留字,并且(
是运算符。迈克尔·霍默(Michael Homer)在注释中也指出了同样的内容-复合命令定义指出(添加了重点):这些复合命令中的每一个在开头都有一个保留字或控制运算符
{
被定义为保留字,类似于Shell语法中列出的for
或while
(请参阅问题中的最后一个代码块)第2.9节规定(强调):
特别是,这些表示包括在某些不需要s的地方(当令牌之一是运算符时)令牌之间的间距。
<blank>
虽然该标准未明确定义
(
为运算符,但(
称为运算符;具体来说,第2.9.2节说如果管道以保留字开头!并且command1是subshell命令,应用程序应确保command1开头的(运算符与!分隔一个或多个字符。保留字!紧跟在(运算符之后)的行为是不确定的。
Digital Trauma 关于堆栈溢出的问题指出了关于保留字的第2.4节:
仅当不引用任何字符且该词用作以下内容时,才发生这种识别:
-命令的第一个字
正如Kusalananda的回答中所述:“ POSIX语法中显示的空格不是shell输入数据中必须存在的空格,而只是显示语法本身的一种方式。事实是,花括号是保留字,这意味着他们已经被空白包围”至于提到的迈克尔·荷马的评论:‘如果空间是在自己的权利显著,他们会需要在上市产品 ’
案件结案。
{
和if (
都视为保留字”cf。“每个复合命令的开头都有保留字或控制运算符 ”。
' '
)。相反,空格由单词标记表示。
command : simple_command | compound_command | compound_command redirect_list | function_definition ;
的产品说明您可以在何处使用命令,它可以是简单命令,复合命令,带重定向的复合命令或函数定义之一。