2017-08-17 1 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_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'); 

を一致させることができます

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'); 

を行うことができます。

すべてが重複しても一致する方法はありますか?それとも、正規表現のマッチを使うのが本質的だから、スピードを落とすべきでしょうか?

+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

関連する問題