Perl glob、qq() 和方括号 []

Sco*_*ott 3 perl glob string-interpolation

我有两个目录,每个目录都有一个文件:

$ ls -l "test dir["
-rw-r--r--  1 root  media     0B 11 Dec 16:53 .ignoreme
Run Code Online (Sandbox Code Playgroud)

$ ls -l "test [dir]"
-rw-r--r--  1 root  media     0B 11 Dec 16:34 .ignoreme
Run Code Online (Sandbox Code Playgroud)

我正在使用 Perl 来测试“.ignoreme”文件是否存在:

$ perl -e '$d="test dir["; print -e glob qq("$d"/.ignore*); print "\n";'
1 
Run Code Online (Sandbox Code Playgroud)

哪个有效,以及

$ perl -e '$d="test [dir]"; print -e glob qq("$d"/.ignore*); print "\n";'

Run Code Online (Sandbox Code Playgroud)

哪个没有。

我猜这与这[]对有关,但我不确定相互作用。有人可以请教我。我也很感谢修复以匹配任何$d包含[].

zdi*_*dim 8

glob解释对[]作为元字符一个字符类这很容易通过一个简单的实验得到证实

mkdir zZ
touch zZ/f.txt
perl -wE'say for glob qq([az][bZ]/*)'
Run Code Online (Sandbox Code Playgroud)

这正确地列出了文件。

然后在问题的第二种情况下,glob根本不查找[]名称中带有文字的目录,而是查找名称中带有任一d,i,r字符的目录test␣

一种解决方法是使用\Q...\E(参见quotemeta)来逃避那些[]

say for glob qq(\Q$d\E/.ignore*);
Run Code Online (Sandbox Code Playgroud)

这也可以根据需要转义空格——但是它也会转义其他内容,因此您不能对序列内的内容使用通配符(对于一个)。这不应该是一个问题,因为目录名称不会包含用作通配符的字符,但最好记住它。

另一种选择是在形成目录名称变量时转义特殊字符

 perl -wE'$d = quotemeta "test [dir]"; say for glob qq($d/*)'
Run Code Online (Sandbox Code Playgroud)

现在照常工作。

不需要双引号,因为quotemeta它也会处理空格。


水珠页说:

该运算符是使用标准File::Glob扩展实现的。

File::Glob文档专门[]列为元字符,用于字符类