51 Stimmen

Überschneidende Übereinstimmungen in Regex

Ich kann anscheinend keine Antwort auf dieses Problem finden und frage mich, ob es eine gibt. Vereinfachtes Beispiel:

Nehmen wir eine Zeichenkette "nnnn", bei der ich alle Übereinstimmungen von "nn" finden möchte - aber auch solche, die sich überschneiden. Die Regex würde also die folgenden 3 Übereinstimmungen liefern:

  1. nn nn
  2. n nn n
  3. nn nn

Mir ist klar, dass dies nicht genau das ist, wofür Regexe gedacht sind, aber das Durchlaufen der Zeichenkette und das manuelle Parsen scheint eine Menge Code zu sein, wenn man bedenkt, dass die Übereinstimmungen in Wirklichkeit mit einem Muster und nicht mit einer wörtlichen Zeichenkette durchgeführt werden müssten.

38voto

VonC Punkte 1117238

Update 2016:

Um die nn , nn , nn , SDJMcHattie schlägt vor in die Kommentare (?=(nn)) (siehe regex101) .

(?=(nn))

Originalantwort (2008)

Eine mögliche Lösung könnte die Verwendung eines positiver Blick zurück :

(?<=n)n

Es würde Ihnen die Endposition von geben:

  1. n n nn  
  2. n n n n  
  3. nn n n

Wie bereits von Timothy Khouri , a positive Vorausschau ist intuitiver ( siehe Beispiel )

Ich würde seinen Vorschlag vorziehen (?=nn)n die einfachere Form:

(n)(?=(n))

Dies würde auf die erste Position der gewünschten Zeichenketten und würde das zweite n in Gruppe(2) erfassen .

Das ist so, weil:

  • Jeder gültige reguläre Ausdruck kann innerhalb des Lookaheads verwendet werden.
  • Enthält sie einschließende Klammern, wird die Rückverweise werden gespeichert .

So erfassen group(1) und group(2), was auch immer "n" darstellt (selbst wenn es sich um einen komplizierten Regex handelt).


31voto

Jan Goyvaerts Punkte 20683

Die Verwendung eines Lookaheads mit einer Erfassungsgruppe funktioniert, macht aber Ihre Regex langsamer und komplizierter. Eine alternative Lösung besteht darin, der Methode Regex.Match() mitzuteilen, wo der nächste Übereinstimmungsversuch beginnen soll. Versuchen Sie dies:

Regex regexObj = new Regex("nn");
Match matchObj = regexObj.Match(subjectString);
while (matchObj.Success) {
    matchObj = regexObj.Match(subjectString, matchObj.Index + 1); 
}

2voto

PhiLho Punkte 39496

AFAIK, gibt es keine reine Regex Möglichkeit, das auf einmal zu tun (dh die drei Erfassungen, die Sie anfordern, ohne Schleife zurückgeben).

Jetzt können Sie ein Muster einmal finden und die Suche ab dem Offset (gefundene Position + 1) in einer Schleife fortsetzen. Sollte Regex Verwendung mit einfachen Code zu kombinieren.

[EDIT] Toll, ich werde heruntergestuft, obwohl ich im Grunde das gesagt habe, was Jan gezeigt hat...
[EDIT 2] Um es klar zu sagen: Jans Antwort ist besser. Sie ist zwar nicht präziser, aber auf jeden Fall ausführlicher und verdient es, ausgewählt zu werden. Ich verstehe nur nicht, warum meine Antwort heruntergestuft wurde, da ich immer noch nichts Falsches darin sehe. Keine große Sache, nur ärgerlich.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X