2011-11-01 84 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的關鍵和價值。這只是您的第一個鍵/值對的例子。