2011-11-01 39 views
2
可变匹配

我希望做在Perl的2步正则表达式查找,我的文字,看起来像这样:2步正则表达式在Perl中

here is some text 9337 more text AA 2214 and some 1190 more BB stuff 8790 words 

我也有一个具有以下值哈希:

%my_hash = (9337 => 'AA', 2214 => 'BB', 8790 => 'CC'); 

这就是我需要做的:

  1. 查找数
  2. 中查找文本代码使用my_hash
  3. 检查是否出现内确定数量为50个字符的文本代码的数量,而如果真打印结果

所以我要找的输出是:

Found 9337, matches 'AA' 
Found 2214, matches 'BB' 
Found 1190, no matches 
Found 8790, no matches 

这是我到目前为止有:

while ($text =~ /(\d+)(.{1,50})/g) { 
    $num = $1; 
    $text_after_num = $2; 
    $search_for = $my_hash{$num}; 
    if ($text_after_num =~ /($search_for)/) { 
    print "Found $num, matches $search_for\n"; 
    } 
    else { 
    print "Found $num, no matches\n"; 
    } 

这类作品的,不同之处在于只正确匹配是9337;代码与2214不匹配。我认为原因在于9337上的正则表达式匹配在第二步匹配的数字之后包含50个字符,然后当正则表达式引擎再次启动时,它将从2214.有没有简单的方法来解决这个问题?我认为\G修饰符可以帮助我,但我不太明白。

任何建议或帮助将是伟大的。

回答

3

你有一个贪婪的问题。 1,50将消耗尽可能多的。你的正则表达式应该是/(\d+)(.+?)(?=($|\d))/

为了解释,问号将使多重匹配非贪婪(它会在下一个模式匹配时立即停止 - 下一个模式优先)。 ?=是一个先行操作符,用于说“检查下一个元素是否是数字,如果是,匹配但不消耗”。这允许第一个数字在正则表达式的开始处被拾取并被放入下一个匹配的模式。

[编辑] 我添加了一个可选的结束值的前瞻,使它不会死在最后一场比赛。

+0

非常感谢Erik。我的数据中还有一个我没有用我的例子捕捉到的皱纹。假设'AA'出现在2214之后 - 你的解决方案将不起作用,对吧?你看到如何做到这一点?再次感谢。 – itzy

+0

你的意思是直接在2214之后2214AA –

+0

可能是这样,或者2214之后的任何地方,但是在9337的50个字符之内。 – itzy

2

只需使用:

/\b\d+\b/g 

为什么,如果你不需要匹配的一切吗?你应该使用其他功能,以确定该号码是:

/(?=9337.{1,50}AA)/ 

如果AA超过50个字符从9337.课程结束后进一步远离你将不得不插值您的变量,以配合这将你的失败hashe的关键和价值。这只是您的第一个键/值对的例子。