“ a [bc] d”(方括号)和“ a {b,c} d”(方括号)有什么区别?


28

a[bc]d和之间有什么区别a{b,c}d?人们为什么要使用a{b,c}d已有的东西a[bc]d


谁叫你用command a[bc]d
Jesse_b

3
如果人们正确地理解它,那么它肯定有其用途。
周伟军

7
我想我只是不了解两者之间是如何发生混乱的。
Jesse_b

一位不太熟悉Linux的同事明确地问过我,虽然不是最近。
周伟俊

@Jesse_b如果您只尝试对像这样的文件进行操作,ls并且仅尝试单个字符,则它们看起来将发挥相同的作用。
Nacht-恢复莫妮卡

Answers:


43

两者是完全不同的。

a[bc]d文件名模式(在以外的shell中fish)。这将扩大到两个文件名 abdacd如果这些是在当前目录中现有文件的名称。

  • [...]部分是带括号的表达式,与列出的字符中的单个字符匹配(或在包括范围时整理元素)。要匹配模式a[bc]d,字符串之间ad文件名中的字符必须为a b或a c

  • 如果abd存在但acd不存在,则它将仅扩展为abd,反之亦然。

  • 如果没有abd,也不是acd存在的,这取决于外壳和选项,它会触发一个错误(原来的Unix sh(t)cshzshfishbash -O failglob),并可能退出shell,或者离开模式unexpanded¹(类似Bourne和rc样弹)或扩展到什么都没有((bash/zsh/yash -o nullglob某些旧版本的fish,原始Unix,sh以及(t)csh同一命令中是否有其他匹配的glob)。

a{b,c}d大括号扩展(在支持这些扩展的shell中)。它将扩展为两个字符串 abdacd

  • {...}部分是一组以逗号分隔的字符串(在此示例中;在某些shell中,它也可能是一个范围,例如a..k20..25或更高级的字符串,例如00..20..20..20..2%02d),并且扩展是通过将这些字符串中的每一个与侧面连接在一起来计算的字符串ad。这些字符串可能比单个字符长,也可能是括号扩展本身。

  • 无论这些字符串是否与现有文件名相对应,都会进行扩展。

如果要构造字符串,请使用大括号扩展名。如果要匹配文件名,请使用文件名模式。


¹在这种情况下,a[bc]d可能恰好是现有文件的名称,这就是为什么rm -f ./*.[ch]在这些shell中使用此类文件可能具有潜在的危险,并且rm -f ./*.{c,h}问题不大。


感谢您澄清“如果abd存在,但acd不存在,那么它只会扩展为abd”。我想这就是我的答案所缺少的。
周伟军

9
另一个重要的区别是,中a{b,c}dbc部分不必为单个字母;例如ex{ten,ci}sion。虽然ex[tenci]sion或任何将只匹配一个这些信件。
alexis

7

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},仅在bash3.0 之后出现,而bash4.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


2
大括号扩展不是“ bashism”;它最早出现在csh很久以前bash。它也存在于glob(3)库函数中。不同之处在于bash它是在其他扩展之前执行的:a=A; ab=A/B; ac=A/C; echo $a{b,c}在bash中的工作方式与任何其他shell不同。
mosvy

谢谢。我将更新答案。
周伟俊
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.