我使用命令在目录中创建了三个文件touch inv{1..3}.txt
。现在我使用了两个命令,它们的输出几乎相同。这两个命令是ls inv[13].txt
和ls {1,3}.txt
。
那么这两者有什么不同?方括号与括号相比有什么不同?另外,我在谷歌上搜索“linux [..]”,但没有找到任何内容,所以我能知道这些东西在 linux 术语中叫什么吗?
谢谢
答案1
{}
称为括号扩展。它有两种形式:{x..y}
和{x,y}
,用任意字母或数字值替换x
和。y
在第一种形式中,
{x..y}
将扩展为从x
到 的所有值y
(包括 )。例如,{2..5}
将扩展为2
、3
、4
、5
。在第二种显式形式中,
{x,y}
将被扩展为仅x
,y
。例如,{2,5}
将被扩展为2
和5
。如果无法扩展,则按字面意思处理该模式,例如
{a..3}
。需要注意的重要一点是,在文件创建/匹配时,无论文件是否匹配,都会进行括号扩展(如果可能)。
[]
被称为路径名扩展(或通配符)模式。与括号扩展不同,您只能在匹配文件名时使用它,如果您在创建文件时使用它,它将被按字面处理。它有两种形式:
[xyz...]
和[x-y]
。在第一种形式中,它将分别匹配方括号内的任意单个字符,即每个字符都单独处理。因此,对于 ,
[25].txt
它将匹配当前目录中名为2.txt
或 的文件5.txt
,而对于 ,[245].txt
它将匹配任何名为2.txt
或4.txt
或 的文件5.txt
。在第二种形式中,首先进行范围扩展,然后进行逐个匹配,如果可能,则按字面处理,否则按字面处理。因此对于
[2-5]. txt
,它将匹配名为2.txt
或3.txt
或4.txt
或 的任何文件5.txt
。如果范围无法扩展,则将按字面处理,例如在 的情况下[a-3].txt
。
这两者之间一个重要的行为差异是当有更多模式需要匹配时,实际上匹配的模式较少。由于无论如何都会进行括号扩展,因此它会显示某些文件不存在的错误,而路径名扩展将匹配任何可能的文件,而不会对其余文件产生任何错误:
$ ls {1..4}.txt
ls: cannot access 4.txt: No such file or directory
1.txt 2.txt 3.txt
$ ls [1-4].txt
1.txt 2.txt 3.txt
可移植性注意事项:
路径[]
名扩展运算符由 POSIX 定义,因此可以在 Bourne shell 及其衍生产品之间移植。
括号扩展{}
不是由 POSIX 定义的,因此无法在所有 shell 之间移植。例如, Ubuntu 中的dash
( sh
) 没有这个。它是从某些 shell 借用的csh
,并且只能在某些 shell 上使用,例如bash
,,,zsh
。ksh93
在fish
实现之前,请确保您使用的 shell 支持此功能。
例子:
$ touch {1..3}.txt
$ ls {1..3}.txt
1.txt 2.txt 3.txt
$ ls {1,2,3}.txt
1.txt 2.txt 3.txt
$ ls {1..4}.txt
ls: cannot access 4.txt: No such file or directory
1.txt 2.txt 3.txt
$ ls {a..3}.txt
ls: cannot access {a..3}.txt: No such file or directory
$ ls [123].txt
1.txt 2.txt 3.txt
$ ls [1-3].txt
1.txt 2.txt 3.txt
$ ls [1-4].txt
1.txt 2.txt 3.txt
$ ls [a-3].txt
ls: cannot access [a-3].txt: No such file or directory
答案2
两种形式之间的主要区别如下所示:
$ ls inv[15].txt
inv1.txt
$ ls inv{1,5}.txt
ls: cannot access 'inv5.txt': No such file or directory
inv1.txt
inv[15].txt
是一个 glob,它将扩展文件系统上匹配文件的列表。这是路径名扩展。
inv{1,5}.txt
扩展到inv1.txt
,而inv5.txt
不管文件系统上实际有哪些文件。这是括号扩展。