Answers:
一个简化的原因是存在一个字符:space。
括号扩展不处理(未引用)空格。
一个{...}
列表需要(未报价)的空间。
更详细的答案是Shell如何解析命令行。
解析(理解)命令行的第一步是将其分为几部分。
这些部分(通常称为单词或标记)是通过从链接中的每个元字符处划分命令行来产生的:
- 将命令拆分为由固定的元字符集分隔的标记:SPACE,TAB,NEWLINE,;,(,),<,>,|和&。令牌的类型包括单词,关键字,I / O重定向器和分号。
元字符:spacetabenter;,<>|和&。
拆分后,单词可能是一种类型(如Shell所理解):
LC=ALL ...
LC=ALL echo
LC=ALL echo "hello"
LC=ALL echo "hello" >&2
仅当“括号字符串”(不带空格或元字符)是单个单词(如上所述)且未加引号时,它才是“括号扩展”的候选者。稍后将在内部结构上执行更多检查。
因此,这:等于或(在bash中,zsh是不同的)被{ls,-l}
称为“括号扩展”变为。ls -l
first word
argument
$ {ls,-l} ### executes `ls -l`
$ echo {ls,-l} ### prints `ls -l`
但这不会:{ls ,-l}
。Bash会继续分裂,space并将行解析为两个单词:{ls
和,-l}
将会触发command not found
(参数,-l}
丢失):
$ {ls ,-l}
bash: {ls: command not found
您的一行:{ls;echo hi}
由于存在两个元字符;和,因此不会成为“括号扩展” space。
它将分为三个部分:{ls
new命令:echo
hi}
。了解;触发器将触发新命令的启动。{ls
找不到该命令,下一条命令将显示hi}
:
$ {ls;echo hi}
bash: {ls: command not found
hi}
如果将其放在其他命令之后,它将始终在以下命令之后启动新命令;:
$ echo {ls;echo hi}
{ls
hi}
其中的“化合物的命令”的是“支撑列表”(我的话): { list; }
。
如您所见,它是用空格和closeing定义的;
。需要
空格,;因为{
和}
都是“保留字 ”。
因此,要被识别为单词,必须将其用元字符包围(几乎总是:)space。
- 检查每个命令的第一个标记以查看它是否为....,{或(,然后该命令实际上是复合命令。
您的示例:{ls;echo hi}
不是列表。
它需要一个结束符,;并且至少要有一个空格{。最后一个}由结束定义;。
这是一个清单{ ls;echo hi; }
。这{ ls;echo hi;}
也是(不太常用,但有效)(感谢@choroba的帮助)。
$ { ls;echo hi; }
A-list-of-files
hi
但是作为命令的参数(shell知道区别),它会触发错误:
$ echo { ls;echo hi; }
bash: syntax error near unexpected token `}'
但是请注意您认为外壳正在解析的内容:
$ echo { ls;echo hi;
{ ls
hi
;
和之间不需要空格}
。{ ls;}
因为分号已经是一个元字符,所以可以使用。
通过检查命令行的语法可以知道。以相同的方式,它知道在表达式中echo echo
,第一个回波应被视为命令,第二个回波应被视为第一个回波的参数。
在bash中,它非常简单,因为{ cmd; }
应该有空格和分号。但是,例如在zsh中并不需要它们,但是仍然可以通过分析{}
shell 上下文来判断应使用其内容做什么。
考虑以下:
alias 1..3=date
{ 1..3; } #in bash
{1..3} #in zsh
两者都返回当前日期,但是
echo {1..3}
返回值,1 2 3
因为shell知道{}
command的参数echo
,因此应将其扩展。
{
其次是未加引号的空格不会在bash中开始大括号扩展。
{
。未加引号的空间不能在任何地方,因为Shell会将整个命令行分割为空格。
首先,复合花括号本身必须是一个单词,也是命令行的第一个单词:
echo { these braces are just words }
其次,单个括号并不特殊(如上所示)。空括号也不是特别的:
echo {} # just the token {}: familiar from the find command
没有逗号的任何东西本身也就是
echo {abc} # just {abc}
这是动作开始的地方。
echo {a,b} # braces disappear, a b results.
因此,基本上,为了使括号扩展生效,我们需要一个单词(在空格中不分隔成多个字段),在其中至少出现一个实例,{...}
在其中至少出现一个逗号。
顺便说一句,这可以是命令行中的第一个单词:
{ls,-l} . # just "ls -l ."
{
被解释为一个命令列表,如果它出现在命令的开始,作为一个括号扩展,否则,但我不知道。