Answers:
两者是完全不同的。
a[bc]d
是文件名模式(在以外的shell中fish
)。这将扩大到两个文件名 abd
及acd
如果这些是在当前目录中现有文件的名称。
该[...]
部分是带括号的表达式,与列出的字符中的单个字符匹配(或在包括范围时整理元素)。要匹配模式a[bc]d
,字符串之间a
和d
文件名中的字符必须为a b
或a c
。
如果abd
存在但acd
不存在,则它将仅扩展为abd
,反之亦然。
如果没有abd
,也不是acd
存在的,这取决于外壳和选项,它会触发一个错误(原来的Unix sh
,(t)csh
,zsh
,fish
,bash -O failglob
),并可能退出shell,或者离开模式unexpanded¹(类似Bourne和rc
样弹)或扩展到什么都没有((bash/zsh/yash -o nullglob
某些旧版本的fish
,原始Unix,sh
以及(t)csh
同一命令中是否有其他匹配的glob)。
a{b,c}d
是大括号扩展(在支持这些扩展的shell中)。它将扩展为两个字符串 abd
和acd
。
该{...}
部分是一组以逗号分隔的字符串(在此示例中;在某些shell中,它也可能是一个范围,例如a..k
或20..25
或更高级的字符串,例如00..20..2
或0..20..2%02d
),并且扩展是通过将这些字符串中的每一个与侧面连接在一起来计算的字符串a
和d
。这些字符串可能比单个字符长,也可能是括号扩展本身。
无论这些字符串是否与现有文件名相对应,都会进行扩展。
如果要构造字符串,请使用大括号扩展名。如果要匹配文件名,请使用文件名模式。
¹在这种情况下,a[bc]d
可能恰好是现有文件的名称,这就是为什么rm -f ./*.[ch]
在这些shell中使用此类文件可能具有潜在的危险,并且rm -f ./*.{c,h}
问题不大。
a{b,c}d
的b
和c
部分不必为单个字母;例如ex{ten,ci}sion
。虽然ex[tenci]sion
或任何将只匹配一个这些信件。
a[bc]d
是模式匹配,是POSIX标准的一部分。在POSIX中,这被称为“模式括号表达式”。手册第2.13节中对此进行了说明
当不加引号且在方括号表达式之外时,以下三个字符在模式规范中应具有特殊含义:
?
问号是一种可以与任何字符匹配的模式。
*星号是应匹配多个字符的模式,如匹配多个字符的模式中所述。
[开括号应引入模式括号表达式。
2.13.3节还提到了一些与常规正则表达式用于文件名扩展的行为不同的行为(我强调)
到目前为止,在模式匹配单个字符和模式匹配多个字符中描述的规则由以下规则限定,这些规则在将模式匹配表示法用于文件名扩展时适用:
路径名中的斜杠字符应通过在模式中使用一个或多个斜杠来明确匹配;它既不能与星号或问号特殊字符匹配,也不能与括号表达式匹配。模式中的斜线应在方括号表达式之前标识;因此,用于文件名扩展的模式括号表达式中不能包含斜杠。如果在找到相应的闭合方括号之前,在未转义的方括号字符之后发现斜线字符,则将该方括号视为普通字符。例如,该模式
"a[b/c]d"
与诸如abd
或的路径名不匹配a/d
。它仅与原义的路径名匹配a[b/c]d
。
a{b,c}d
是括号扩展,不是POSIX规范中的。这是bash 手册中的相应部分(我强调):
括号扩展是一种可以生成任意字符串的机制。此机制类似于文件名扩展(请参阅文件名扩展),但是生成的文件名不必存在。花括号扩展的模式采用可选的前导形式, 然后是一系列用逗号分隔的字符串或一对花括号之间的序列表达式,然后是可选的 后记。前缀在花括号中包含的每个字符串之前加上前缀,然后将后记附加到每个结果字符串之后,从左向右扩展。
根据@mosvy的评论,这是第一次出现,csh
但是in中的行为bash
不同于csh
和其他shell。牙套的这种扩张也存在于glob(3)
。
括号扩展还有另一种类型{a..z}
,仅在bash
3.0 之后出现,而bash
4.0中又添加了更多种。
在打开了globbing的shell中,在一个空文件夹中执行,返回以下结果
$ echo a[bc]d
a[bc]d
$ echo a{b,c}d
abd acd
作为对@Jesse_b的评论的回应,如果您处于交互式外壳中,并且两者都适用,a[bc]d
则键入时的麻烦就更少了。例如grep pattern [ab][12].txt
。
csh
很久以前bash
。它也存在于glob(3)库函数中。不同之处在于bash
它是在其他扩展之前执行的:a=A; ab=A/B; ac=A/C; echo $a{b,c}
在bash中的工作方式与任何其他shell不同。
command a[bc]d
?