使用双感叹号在perl中匹配cond

matching cond in perl using double exclaimation

if ($a =~ m!^$var/!)

$var 是二维散列中的键,$a 是另一个散列中的键。

这些表达式是什么意思?

这是一个regular expression ("regex"), where the ! character is used as the delimiter for the pattern that is to be matched in the string that it binds to via the =~ operator(这里是$a)。

可能会考虑使用通常的定界符 $a =~ /^$var\// 来考虑相同的正则表达式(然后可以省略 m);但是现在显然必须转义模式中使用的任何 / 。为了避免难看和嘈杂的 \/ 组合,人们经常使用另一个字符作为分隔符,因为几乎可以使用任何字符(我最喜欢的是卷曲,m{^$var/})。 §

问题中的这个正则表达式测试变量 $a 中的值是否以(通过 ^ anchor)变量的值 $var 开头,然后是 /(评估变量并使用结果)。 §


不是变量名的好选择,因为 $a$b 被内置 sort[=43= 使用]

有了提前准备好的模式,甚至不需要分隔符

my $re = qr{^$var/};

if ($string =~ $re) ...

(但我还是喜欢用 // 然后,发现它更清晰)

上面我使用了 qr,但是一个简单的 q() 就可以了(虽然我绝对推荐 qr)。这些也几乎可以使用任何字符作为分隔符。


§ 在一个模式中,评估的变量被用作正则表达式模式,一般来说这是错误的(当这是预期的时候,它们应该使用 qr 进行编译,因此用作子模式)。

一个缺乏想象力的例子:一个变量 $var = q(\s)(文字反斜杠后跟字母 s)在一个模式中计算产生 \s 序列,然后将其视为正则表达式模式,因为空格。 (大概是无意的;我们只是想要 \s。)

这可以通过使用 quotemeta/\Q$var\E/ 来补救,以便转义 $var 中可能的元字符;这导致文字字符的正确模式 \s。所以正确的写法是 m{^\Q$var\E/}.

不这样做也会导致注入错误。感谢 ikegami 对此发表评论。

匹配运算符 (m/.../) 是 Perl 的“类引号”运算符之一。标准用法是在运算符中间的正则表达式前后使用斜杠(如果使用斜杠,则可以省略运算符开头的 m)。但是,如果正则表达式本身包含一个斜线,那么使用不同的分隔符来避免必须转义嵌入的斜线会很方便。在您的示例中,作者决定使用感叹号,但可以使用任何非空白字符。

许多 Perl 运算符都是这样工作的 - m/.../s/.../.../tr/.../.../q/.../qq/.../qr/.../qw/.../, qx/.../(我可能忘记了一些)。