带有特殊字符匹配的预编译正则表达式

时间:2016-08-30 07:02:39

标签: regex perl

如果*FOO(*作为普通字符)这样的单词在一行中,我会尝试匹配。我的输入是C ++源代码。由于程序流程要求,我需要使用预编译的正则表达式,所以我尝试了以下内容:

$pattern = qr/[^a-zA-Z](\*FOO)[^a-zA-Z]|^\s*(\*FOO)[^a-zA-Z]/;

我这样使用它:

if ($line =~ m/$pattern/) { ... }

它有效并捕获包含*FOO的行,例如hey *FOO.BAR,但也匹配以下行:

//FOO programming using stuff and things

我想忽略。我错过了什么? \*不是在perl中预先编译的正则表达式中转义*的正确方法吗?如果*FOO存储在$word中且模式如下:

$pattern = qr/[^a-zA-Z](\\$word)[^a-zA-Z]|^\s*(\\$word)[^a-zA-Z]/;

这与之前的模式不同吗?因为我试过两个,结果似乎是一样的。

我找到了一种绕过此问题的方法,删除了$word中的第一个字符并在模式中转义*,但如果$word = "**.?FOO"例如,我该如何创建{{ 1}}使用qr//以便所有元字符都被转义?

2 个答案:

答案 0 :(得分:1)

问题1:

my $word = '*FOO';
my $pattern = qr/\\$word/;

相当于

my $pattern = qr/\\*FOO/; # zero or more '\' followed by 'FOO'

$word只是按原样插值。

获得与

等效的东西
my $pattern = qr/\*FOO/;

你应该使用

my $word = '*FOO';
my $pattern = qr/\Q$word\E/;

默认情况下,插值变量被视为迷你正则表达式,变量中的元字符(如*+?仍被解释为元字符。 \Q...\E会在任何不匹配/[A-Za-z_0-9]/的字符之前添加反斜杠,因此插值变量中的任何元字符都会被解释为文字字符。请参阅perldoc

问题2

我试过

my $pattern = qr/[^a-zA-Z](\*FOO)[^a-zA-Z]|^\s*(\*FOO)[^a-zA-Z]/;
my $line = '//FOO programming using stuff and things';

if($line =~ m/$pattern/){
    print "$&\n";
}
else{
    print "No match!";
}

它打印了#34;不匹配!"。我无法解释你是如何匹配它的。

答案 1 :(得分:1)

你需要逃避*。一种方法是quotemeta

use warnings;
use strict;

my $qr = /\Q*FOO/;

while (<DATA>) { print if /$qr/ }

__DATA__
//FOO programming using stuff and things
hey *FOO.BAR

这确定*FOO是否在行中,无论它是单词还是单词的一部分。我不清楚问题是什么情况。一旦指定,就可以调整模式。

请注意,/\*FOO/也有效。你尝试失败的原因可能是因为你想要匹配的其余部分,我不明白的目的。如果您只需要检测模式是否存在,则上述操作。如果有更具体的要求请澄清。