45

この問題に対する答えが見つからないようで、存在するかどうか疑問に思っています。簡単な例:

「nn」のすべての一致を検索したい文字列「nnnn」を考えてみますが、互いに重複するものも検索します。したがって、正規表現は次の 3 つの一致を提供します。

  1. んんん_
  2. n n n
  3. んんん_

これは正確には正規表現が意図するものではないことは理解していますが、実際にはリテラル文字列ではなくパターンを使用して一致を行う必要があることを考えると、文字列を調べてこれを手動で解析するのは非常に多くのコードのように思えます。

4

3 に答える 3

30

更新 2016:

nn, nn,を取得するにはnnSDJMcHattieがコメント で提案しています(?=(nn))(regex101 を参照)

(?=(nn))

元の回答 (2008)

考えられる解決策は、肯定的な後ろ姿を使用することです。

(?<=n)n

次の最終位置が得られます。

  1. nnnn _ _  
  2. n n n n  
  3. んんんん_ _

Timothy Khouriが述べたよう に、前向きな先読みはより直感的です (例を参照) 。

私は彼の命題(?=nn)nよりも単純な形式を好みます:

(n)(?=(n))

これは、必要な文字列の最初の位置を参照し、 group(2) の 2 番目の n をキャプチャします。

その理由は次のとおりです。

  • 有効な正規表現は、先読み内で使用できます。
  • キャプチャ括弧が含まれている場合、後方参照は保存されます。

したがって、group(1) と group(2) は、'n' が表すものを (複雑な正規表現であっても) キャプチャします。


于 2008-11-26T12:01:56.787 に答える
29

キャプチャ グループで先読みを使用すると、正規表現が遅くなり、複雑になるという犠牲を払って機能します。別の解決策は、Regex.Match() メソッドに次の一致の試行を開始する場所を伝えることです。これを試して:

Regex regexObj = new Regex("nn");
Match matchObj = regexObj.Match(subjectString);
while (matchObj.Success) {
    matchObj = regexObj.Match(subjectString, matchObj.Index + 1); 
}
于 2008-11-26T16:52:39.230 に答える
2

私の知る限り、一度にそれを行うための純粋な正規表現の方法はありません(つまり、ループなしで要求した3つのキャプチャを返します)。

これで、パターンを 1 回見つけて、オフセット (見つかった位置 + 1) から始まる検索をループすることができます。正規表現の使用と単純なコードを組み合わせる必要があります。

[編集] 素晴らしい、基本的にヤンが示したことを言ったとき、私は反対票を投じました...
[編集2] 明確にするために: ヤンの答えはより良いです。より正確ではありませんが、確かにより詳細であり、選択する価値があります。私はまだ何も間違っていないので、なぜ私のものが反対票を投じられたのか理解できません。大したことではありません、ただ迷惑です。

于 2008-11-26T11:57:56.343 に答える