Weijun Zhou Asked: 2019-04-28 09:35:59 +0800 CST2019-04-28 09:35:59 +0800 CST 2019-04-28 09:35:59 +0800 CST `a[bc]d`(方括号)和 `a{b,c}d`(大括号)有什么区别? 772 a[bc]d和 和有什么不一样a{b,c}d?为什么人们a{b,c}d在已经有的时候使用a[bc]d? brace-expansion pattern-matching 2 个回答 Voted Best Answer Kusalananda 2019-04-28T10:41:50+08:002019-04-28T10:41:50+08:00 两者完全不同。 a[bc]d是一个文件名模式(在 以外的 shell 中fish)。它将扩展到两个文件名 abd,acd如果它们是当前目录中现有文件的名称。 该[...]部分是一个括号表达式,它匹配列出的字符中的单个字符(或在包括范围时整理元素)。要匹配模式a[bc]d,字符串之间a和d文件名中的字符必须是 ab或 a c。 如果abd存在但acd不存在,那么它只会扩展为abd,反之亦然。 如果两者都不存在abd,也不acd存在,具体取决于 shell 和选项,它将触发错误(原始 Unix sh、(t)csh、zsh、fish、bash -O failglob)并可能退出 shell,或者使模式保持未扩展¹(Bourne-like 和rc-like shell)或扩展为什么都没有(bash/zsh/yash -o nullglob、一些旧版本的fish、原始 Unixsh以及(t)csh同一命令中是否有其他匹配的 glob)。 a{b,c}d是一个大括号扩展(在支持这些的 shell 中)。它将扩展到两个字符串 abd和acd. 该{...}部分是一组以逗号分隔的字符串(在此示例中;在某些 shell 中,它也可能是诸如a..k或之类或20..25更高级的范围),并且通过将这些字符串中的每一个与侧翼组合来计算扩展字符串和. 这些字符串可能比单个字符长,也可能是大括号扩展本身。00..20..20..20..2%02dad 无论这些字符串是否对应于现有文件名,都会发生扩展。 如果您正在构造字符串,请使用大括号扩展。如果要匹配文件名,请使用文件名模式。 ¹在这种特殊情况下,a[bc]d可能恰好是现有文件的名称,这就是为什么rm -f ./*.[ch]在这些 shell 中使用类似的东西可能很危险,而且rm -f ./*.{c,h}问题不大。 Weijun Zhou 2019-04-28T09:35:59+08:002019-04-28T09:35:59+08:00 a[bc]d是模式匹配,并且是 POSIX 标准的一部分。在 POSIX 中,这是作为“模式括号表达式”引入的。它记录在手册的第 2.13 节中 当不带引号且在括号表达式之外时,以下三个字符在模式规范中应具有特殊含义: ? 问号是一种可以匹配任何字符的模式。 * 星号是应匹配多个字符的模式,如匹配多个字符的模式中所述。 [ 开放括号应引入模式括号表达式。 第 2.13.3 节还提到了一些事情,当它用于文件名扩展时,它的行为与通常的正则表达式不同(我强调) 到目前为止,在匹配单个字符的模式和匹配多个字符的模式中描述的规则由以下规则限定,这些规则适用于将模式匹配表示法用于文件名扩展时: 路径名中的斜线字符应通过在模式中使用一个或多个斜线来显式匹配;它既不能与星号或问号特殊字符匹配,也不能与括号表达式匹配。模式中的斜线应在括号表达式之前标识;因此,斜线不能包含在用于文件名扩展的模式括号表达式中。如果在未转义的左方括号字符之后发现一个斜线字符,然后找到相应的右方括号,则该左方括号应被视为普通字符。例如,该模式 与或"a[b/c]d"等路径名不匹配。它只匹配字面上的路径名。abda/da[b/c]d a{b,c}d是大括号扩展,它不在 POSIX 规范中。这是 bash手册中的相应部分(我强调): 大括号扩展是一种可以生成任意字符串的机制。这种机制类似于文件名扩展(参见文件名扩展),但生成的文件名不需要存在。要进行大括号扩展的模式采用可选前导码的形式, 后跟一系列逗号分隔的字符串或一对大括号之间的序列表达式,然后是可选的 后记。序言作为前缀添加到大括号中包含的每个字符串,然后将后记附加到每个结果字符串,从左到右扩展。 根据@mosvy 的评论,这首先出现在csh但行为bash不同于csh其他shell。这种类型的大括号扩展也存在于glob(3). 还有一种大括号扩展是3.0{a..z}以后才出现的, 4.0以后多了。bashbash 在开启了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.
两者完全不同。
a[bc]d
是一个文件名模式(在 以外的 shell 中fish
)。它将扩展到两个文件名abd
,acd
如果它们是当前目录中现有文件的名称。该
[...]
部分是一个括号表达式,它匹配列出的字符中的单个字符(或在包括范围时整理元素)。要匹配模式a[bc]d
,字符串之间a
和d
文件名中的字符必须是 ab
或 ac
。如果
abd
存在但acd
不存在,那么它只会扩展为abd
,反之亦然。如果两者都不存在
abd
,也不acd
存在,具体取决于 shell 和选项,它将触发错误(原始 Unixsh
、(t)csh
、zsh
、fish
、bash -O failglob
)并可能退出 shell,或者使模式保持未扩展¹(Bourne-like 和rc
-like shell)或扩展为什么都没有(bash/zsh/yash -o nullglob
、一些旧版本的fish
、原始 Unixsh
以及(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[bc]d
是模式匹配,并且是 POSIX 标准的一部分。在 POSIX 中,这是作为“模式括号表达式”引入的。它记录在手册的第 2.13 节中第 2.13.3 节还提到了一些事情,当它用于文件名扩展时,它的行为与通常的正则表达式不同(我强调)
a{b,c}d
是大括号扩展,它不在 POSIX 规范中。这是 bash手册中的相应部分(我强调):根据@mosvy 的评论,这首先出现在
csh
但行为bash
不同于csh
其他shell。这种类型的大括号扩展也存在于glob(3)
.还有一种大括号扩展是3.0
{a..z}
以后才出现的, 4.0以后多了。bash
bash
在开启了globbing的shell中,在空文件夹中执行,返回如下结果
作为对@Jesse_b 评论的回应,如果您在交互式外壳中并且它们都适用,
a[bc]d
那么打字的麻烦就更少了。例如grep pattern [ab][12].txt
.