5

在阅读了这个类似的问题并多次尝试了我的代码之后,我继续得到相同的不想要的输出。

假设我正在搜索的字符串是“我昨天看到了 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$1and $2,你可以注意到。

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

4

3 回答 3

3

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

(?=\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) 的示例代码来查看结果。

于 2013-07-10T21:12:11.600 回答
1

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

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

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

pos()函数允许您指定/g正则表达式从何处开始搜索。

于 2013-07-10T21:03:33.230 回答
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

于 2013-07-10T21:17:48.673 回答