使用Perl中的regex在字符串中获取多个匹配项

时间:2013-07-10 20:56:22

标签: regex perl multiple-matches

在阅读this similar question并多次尝试我的代码之后,我继续获得相同的不良输出。

让我们假设我正在搜索的字符串是“我昨天看到了wilma”。 正则表达式应该捕获每个单词后跟一个'a'及其可选 5个字符或空格。

我写的代码如下:

$_ = "I saw wilma yesterday";

if (@m = /(\w+)a(.{5,})?/g){
    print "found " . @m . " matches\n";

    foreach(@m){
        print "\t\"$_\"\n";
    }
}

但是,我继续得到以下输出:

found 2 matches
    "s"
    "w wilma yesterday"

虽然我希望得到以下内容:

found 3 matches:
    "saw wil"
    "wilma yest"
    "yesterday"

直到我发现@m内的返回值为$1$2,您可以注意到。

现在,由于/g标志已打开,我认为问题不在于正则表达式,我怎样才能获得所需的输出?

3 个答案:

答案 0 :(得分:2)

您可以尝试这种允许重叠结果的模式:

(?=\b(\w+a.{1,5}))

(?=(?i)\b([a-z]+a.{0,5}))

示例:

use strict;
my $str = "I saw wilma yesterday";
my @matches = ($str =~ /(?=\b([a-z]+a.{0,5}))/gi);
print join("\n", @matches),"\n";

更多解释:

你不能与正则表达式重叠结果,因为当正则表达式引擎“吃掉”一个字符时,它不能再次被吃掉。避免这种约束的诀窍是使用前瞻(这是一种只检查但不匹配的工具),它可以多次运行字符串,并将捕获组放入其中。

对于此行为的另一个示例,您可以尝试不带字边界(\b)的示例代码来查看结果。

答案 1 :(得分:1)

首先,您要捕获表达式中的所有内容,即:

/(\w+a(?:.{5,})?)/

接下来,您希望从最后一个表达式的第一个字符匹配的一个字符开始搜索。

pos()功能可让您指定/g正则表达式开始搜索的位置。

答案 2 :(得分:1)

$s = "I saw wilma yesterday";    
while ($s =~ /(\w+a(.{0,5}))/g){
    print "\t\"$1\"\n";
    pos($s) = pos($s) - length($2); 
}

给你:

"saw wil"
"wilma yest"
"yesterday"

但我不知道为什么你应该day而不是yesterday