2009-06-03 16 views
8

正規表現で繰り返し数パターンを検出することはできますか?文字列内の繰り返しを検出する正規表現

たとえば、次の文字列「034503450345」がある場合、繰り返しシーケンス0345と一致する可能性がありますか?私はこれが正規表現の範囲を超えていると感じていますが、私は何かを逃してしまったかどうかを私に見て欲しいと思っていました。

+1

あなたはどのような言語/プラットフォームを使用していますか? –

+0

私はC#を使用しています。私が必要としたのは正規表現だけだったので、私はRichieHindleのソリューションを実装し、テストデータに対してすでに検証しました!私はPeter Boughtonの優れたコメントの正規表現から多くのことを学びました。両方のおかげで! –

+0

@MarkWithers私は同じ問題を扱っています。より具体的になり、あなたの解決策についてもっと教えてください。ありがとうございました – user2179427

答えて

9

はい、あなたがすることができます - ここでは、Pythonのテストケース正規表現は言う

import re 
print re.search(r"(\d+).*\1", "8034503450345").group(1) 
# Prints 0345 

だ「数字のいくつかのシーケンスを、他のものの後、任意の量、そして同じシーケンスを再び見つけます。」かろうじて関連のノートで

は、ここに私の好きな正規表現の一つだ - 素数検出器:

import re 
for i in range(2, 100): 
    if not re.search(r"^(xx+)\1+$", "x"*i): 
     print i 
+0

素数検出器で0と1が素数であることがわかります:-) – balpha

+0

なぜ次の例が「0345」ではなく「8」にマッチするのか? FOO = re.search(R "(\ D +)* \ 1。"、 "80345824103452420345")[19]で :foo.groups() OUT [19]:( '8 [18]において '、) –

+0

@balpha:良いpont - 固定。 8-) – RichieHindle

19

この式は、1つまたは複数の繰り返しのグループにマッチします:

(.+)(?=\1+) 


ここでは同じ表現を分解しています(コメントを使用しているので、そのまま正規表現としても使用できます)。

(?x) # enable regex comment mode 
( # start capturing group 
.+ # one or more of any character (excludes newlines by default) 
)  # end capturing group 
(?= # begin lookahead 
\1+ # match one or more of the first capturing group 
)  # end lookahead 


例えば、特定のパターンと一致するパターンに.+を変更します1つ以上の数字の場合は\d+、4つ以上の数字の場合は\d{4,}です。

パターンの特定の番号を一致させるには、\1{4}のように4回繰り返すことで\1+に変更します。

繰り返しが隣り合わないようにするには、先読みの内側に.*?を追加します。

+1

大きな説明+1 – ichiban

+0

良い例、非常によく説明された –

+0

大きな説明。優れた伸長。ありがとう!! +1 – Toto

8

だけRichieHindleから(正しい)解答にメモを追加する:Pythonの正規表現の実装(および、そのようなPerlの他の多く、)一方では、これを行うことができ

注、これはもはや正規表現であります狭い意味の単語。

あなたの例は標準的な言語ではないため、純粋な正規表現では処理できません。例えば、詳しくはWikipedia articleをご覧ください。

これは主に学術的関心事ですが、実際的な結果がいくつかあります。実際の正規表現は、この場合よりも最大ランタイムをより良く保証することができます。だから、ある時点でパフォーマンスの問題が発生する可能性があります。

これは良い解決策ではありませんが、正規表現が(拡張形式であっても)どのような制限があるのか​​を理解しておく必要があります。 。

+0

非常に面白い読書、ありがとう。 –

2

これは、逆参照構造を使用して繰り返し数字を検索するC#コードです。 034503450345、123034503450345、034503450345345、232034503450345423で動作します。正規表現はずっと簡単で分かりやすくなります。

/// <summary> 
/// Assigns repeated digits to repeatedDigits, if the digitSequence matches the pattern 
/// </summary> 
/// <returns>true if success, false otherwise</returns> 
public static bool TryGetRepeatedDigits(string digitSequence, out string repeatedDigits) 
{ 
    repeatedDigits = null; 

    string pattern = @"^\d*(?<repeat>\d+)\k<repeat>+\d*$"; 

    if (Regex.IsMatch(digitSequence, pattern)) 
    { 
     Regex r = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled); 
     repeatedDigits = r.Match(digitSequence).Result("${repeat}"); 
     return true; 
    } 
    else 
     return false; 
} 
+0

非常に良い!私は指定されたグループの使用が好きです。制作品質のコードで、コメントを付けてコピーする準備ができました。どうもありがとう! –

+0

「準備ができました」:D ..私はそれが好きです!!!! –

0

使用正規表現の繰り返し: バー{2、} が二つ以上のバーでテキストを探します。 BARBAR barbarbar ...

関連する問題