试着向前看并向后看

时间:2012-12-07 21:38:25

标签: regex perl

我已经设置了一个简单的测试来测试URL中的/后面的'Home'这个词。我没有前瞻/后面的工作,但是想用它们来做同样的事情。

my $page = "/Home"; #should 'match'
#or
$page = "/New Homes"; #should 'no match'

#A
if ($page =~ /Home | Home/) {
    print "no match A";
} else {
    print "match A";
}
print "\n\n";

#B
if ($page =~ /(?<= )Home(?= )/) {
    print "no match B";
} else {
    print "match B";
}

返回:

no match A
match B #incorrect

那么我没有得到什么?

3 个答案:

答案 0 :(得分:2)

在你的例子中:

(?<= )Home(?= )

你在这里做的是在家之前和之后搜索一个空的空间(或空白)。您想将搜索字符串放在括号内。要在/之前搜索home,请使用此选项:

(?<=\/)Home

另外,作为一个注释,有前瞻和后视,它们不会作为匹配返回,它们只是用于查找匹配。因此,在上面的示例中,Home将作为匹配项返回,而不是/Home

注意:正如评论中指出的那样,perl要求/进行转义。我编辑了代码以包含转义/

答案 1 :(得分:1)

我不知道为什么你认为这两种模式是等价的。

/(?<= )Home(?= )/

匹配与

相同的字符串
/ Home /

不包括匹配中的空格,

/Home(?= )|(?<= )Home/

匹配与

相同的字符串
/Home | Home/

不包括匹配中的空格。


你可能想要:

m{(?<![^/])Home(?![^/])}

类似
m{(?<=/)Home(?=/)}

除了(?<![^/])也匹配字符串的开头,(?![^/])也匹配字符串的末尾。

答案 2 :(得分:0)

您的代码让我感到困惑,也许您也是如此。

my $page = "\/Home"; #should 'match'
#or
$page = "\/New Homes"; #should 'no match'

相当于

my $page = '/New Homes';

因为不需要在文字字符串中转义斜杠,除非需要插入变量,否则不需要使用双引号。

也是这个

if ($page =~ /Home | Home/) {
    print "no match A";
} else {
    print "match A";
}

在匹配时打印no match A,反之亦然,因此no match A的输出正确,因为' Home' 出现在{{ 1}}。

您担心的情况

$page

有同样的问题,它会在匹配时打印if ($page =~ /(?<= )Home(?= )/) { print "no match B"; } else { print "match B"; } 。它正在寻找no match B,前后跟一个空格。 Home包含$page,其前面有'/New Homes',但后面没有空格。所以它说'Home'因为没有匹配。

尝试使用此计划的变体,更正match Bmatch的感觉,并添加no matchuse strict

use warnings

<强>输出

use strict;
use warnings;

my $page = '/New Homes';

if ($page =~ /Home | Home/) {
  print 'match A';
}
else {
  print 'no match A';
}

print "\n\n";

if ($page =~ /(?<= )Home(?= )/) {
  print 'match B';
}
else {
  print 'no match B';
}