2017-08-17 18 views
6

我可以從​​答案看到,如果我做如何在Perl中找到正則表達式匹配的_all_位置?

sub match_all_positions { 
    my ($regex, $string) = @_; 
    my @ret; 
    while ($string =~ /$regex/g) { push @ret, $-[0] } 
    return @ret 
} 

print join ',', match_all_positions('0{3}', '001100010000'); 

我得到

4,8 

什麼我需要做的就是的所有匹配索引,重疊甚至當,這樣的作爲上面例子中的位置8和9?

我可以做

sub match_all_positions_b { 
    my ($substr, $string) = @_; 
    return unless index($string, $substr) > 0; 
    my @res; 
    my $i = 0; 
    while ($i <= (length($string) - $length)) { 
     $i = index($string, $substr, $i); 
     last if $i < 0; 
     push @res, $i++; 
    } 
    return @res; 
} 

print join ',', match_all_positions_b('000', '001100010000'); 

剛剛讓我匹配串,或

sub match_all_positions_c { 
    my ($substr, $string) = @_; 
    my $re = '^' . $substr; 
    my @res; 
    for (0..(length($string) - $length)) { 
     push @res, $_ if substr($string, $_) =~ /$re/; 
    } 
    return @res; 
} 

print join ',', match_all_positions_c('0{3}', '001100010000'); 

這是慢一倍。

有沒有辦法讓全部匹配,即使它們重疊?或者我應該採取速度損失,因爲它是使用正則表達式匹配固有的?

+1

某些樣本數據將是有益的。重疊匹配的標準「技巧」是零寬度斷言。 – Sobrique

+0

@Sobrique - 有關數據,請參閱代碼示例。 'match_all_positions('0 {3}','001100010000');'應該返回'(4,8,9)'; 'match_all_positions('2 {3}','001100010000');'應該返回'()';它的工作原理是 – simone

回答

7

你需要更新你的正則表達式來匹配zero-width look-ahead

嘗試調用你的函數是這樣的:

print join ',', match_all_positions('(?=0{3})', '001100010000'); 
+1

。現在我只需要閱讀文檔並找出原因。謝謝!它的速度也非常快。 – simone

+3

這是因爲通常正則表達式_consume_和所以匹配從池中刪除子匹配。零寬度不消耗,它'放回東西'被重用。 – Sobrique

0

如果你想找到它相匹配的位置:

my @matches; 
push @matches, "$-[1]:$+[1]" while "aabbcc" =~ /(?=(a.*c))/sg; 

輸出:

0:6 
1:6 

如果你想要所有可能的匹配,

local our @matches; 
"aabbcc" =~ /(a.*?c)(?{ push @matches, "$-[1]:$+[1]" })(?!)/s; 

輸出:

0:5 
0:6 
1:5 
1:6 
+0

非常好 - 但需要一些思考:-) – pitseeker