2008-11-10 13 views
32

Ist es möglich, ein paar Zeichen in einer Erfassungsgruppe in regulären Ausdrücken zu überspringen? Ich benutze .NET Regexes, aber das sollte keine Rolle spielen.Regelmäßiger Ausdruck zum Überspringen von Zeichen in Erfassungsgruppe

Im Grunde, was ich suche ist:

[random text] AB123 [random text]

und ich brauche 'AB123' zu erfassen, ohne den Bindestrich.

Ich weiß, dass AB 2 oder 3 Großbuchstaben und 123 ist 2 oder 3 Ziffern, aber das ist nicht der schwierige Teil. Der schwierige Teil (zumindest für mich) ist das Überspringen des Bindestrichs.

Ich denke, ich könnte beide separat erfassen und dann verketten sie in Code, aber ich wünschte, ich hätte eine elegantere, Regex-only-Lösung.

Irgendwelche Vorschläge?

+0

in Javascript verwendet wurde, konnte man: /(AB)\-(123))/.exec("[random text] AB-123 [random Text ] "); es gibt jetzt Array zurück [1] und [2] ^^ – hanshenrik

+0

Wie wäre es mit positivem Lookahead (? =) und positivem Lookbehind (? <=)? Grundsätzlich gilt: (? <= \ ') ([A-Z] {2} - [0-9] {3}) (? = \') Sollte funktionieren. –

Antwort

41

Kurz: Sie können nicht. Eine Übereinstimmung ist immer aufeinanderfolgend, selbst wenn sie Dinge als Assertionen mit einer Breite von Null enthält, gibt es keine Möglichkeit, das nächste Zeichen zu finden, wenn Sie zu dem nächsten Zeichen gelangen wollen.

+0

Sie können positiven Lookbehind und positiven Lookahead verwenden –

+2

True. Aber Lookaround * passt * überhaupt nichts. Die Position der Position Regex-Engine im Stachel ändert sich nicht. – Tomalak

15

Es gibt wirklich keine Möglichkeit, einen Ausdruck so zu erstellen, dass der übereinstimmende Text sich vom Inhalt des Quelltexts unterscheidet. Sie müssen den Bindestrich in einem separaten Schritt entfernen, entweder durch die ersten und zweite Teile individuell passenden und Verketten der zwei Gruppen:

match = Regex.Match(text, "([A-B]{2,3})-([0-9]{2,3})"); 
matchedText = string.Format("{0}{1}", 
    match.Groups.Item(1).Value, 
    match.Groups.Item(2).Value); 

Oder durch den Bindestrich in einem Schritt getrennt von dem Anpassungsvorgang zu entfernen:

match = Regex.Match(text, "[A-B]{2,3}-[0-9]{2,3}"); 
matchedText = match.Value.Replace("-", ""); 
+2

Es gibt auch 'match.Result („$ 1 $ 2“)' –

4

Ihre Behauptung, dass es nicht möglich ist, ohne Untergruppierung + concatentating es ist richtig.

Sie könnten auch tun, wie Jeff-Hillman und nur die schlechten Zeichen nach der Tatsache ausziehen.

Wichtig zu beachten, dass Sie "Regex nicht für alles verwenden".

Regex ist für weniger komplizierte Lösungen für nicht-triviale Probleme gedacht, und Sie sollten nicht "oh, wir verwenden einen Regex" für alles verwenden, und Sie sollten nicht in die Gewohnheit zu denken, dass Sie lösen können das Problem in einem einstufigen Regex.

Wenn es eine praktikable triviale Methode gibt, die funktioniert, verwenden Sie sie auf jeden Fall. Eine alternative Idee, wenn Sie mehrere Übereinstimmungen in einem Hauptteil von Code zurückgeben müssen, suchen Sie nach Ihren Sprachen "Callback" -basierten Regex, die jede gefundene/gefundene Gruppe zu einem Funktionsaufruf, der in tun kann Line-Substitution. (Besonders praktisch, wenn regexp ersetzt wird).

Nicht sicher, wie es funktionieren würde.Net, aber in PHP würden Sie so etwas wie (nicht genaue Code)

function strip_reverse($a) 
    { 
    $a = preg_replace("/-/", "", $a); 
    return reverse($a); 
    } 
    $b = preg_replace_callback("/(AB[-]?cde)/" , 'strip_reverse' , "Hello World AB-cde" ; 
+1

Es ist ein weit verbreitetes Missverständnis, das für „weniger kompliziert siutations“ regex ist nur. Regex ist immens leistungsstark und löst wirklich komplexe Dinge. Regex ist einfach nicht das richtige Werkzeug für Dinge, die nicht regelmäßig sind. Es ist einfach: Es gibt Dinge, die mit Regex funktionieren, und solche, die nicht funktionieren. – Tomalak

+0

ja, aber es gibt eine produktive/übermäßige/regex in Situationen, in denen die Lösung eine Waffe verwendet, um Papier zu stanzen. Es wird funktionieren, aber es gibt Komplikationen, die in der einfacheren Lösung nicht existieren. Der Schlüssel ist zu wissen, wann * nicht * Regex zu verwenden;) –

+0

Wissen, wann welches Werkzeug zu verwenden ist immer der Schlüssel. Ich würde wahrscheinlich vermeiden, Regex in einer langen Schleife zu verwenden, wenn es einen anderen Weg gab (sagen wir "indexOf" plus etwas Mathematik). – Tomalak

1

tun Sie verschachtelte Capture-Gruppen verwenden können, wie folgt aus:

((AB)-(123)) 

Die erste Capture-Gruppe ist AB-123, die zweite ist AB, und das dritte ist 123. Dann müsst ihr nur der zweiten und dritten Gruppe mit einem Leerzeichen beitreten.

+0

Die OP sagte er bereits zu dieser Option kennt. Er denkt nur, dass es einen eleganteren Weg geben sollte. –

0

Art der spät, aber ich denke, ich dieses herausgefunden. Mindestens eine Möglichkeit, es zu tun.

habe ich positive Vorschau bei dem # Zeichen in meinem Text zu stoppen. Ich wollte den Platz oder das # Zeichen nicht, also musste ich einen Ausweg finden, um über sie "zu überspringen". Als ich gezwungen wurde, sie wieder zu vergleichen, habe ich sie in eine Müllgruppe geworfen, die ich nicht verwenden wollte (.ie, ein kleiner Eimer), was im Code ist. Nun, mein Platzzeiger ist eine Zeichenposition hinter dem # -Zeichen (wo ich sein möchte, überspringe das Leerzeichen und das # -Zeichen). Und ich passe jetzt einfach an das Ende des Dateinamens an. und ignoriere die Dateiendung.

(?i)English\\(?<Series>[^ ]+) - (?<Title>.+(?= #))(?<garb1>..)(?<Number>[^.]+)(?-i) 

Der Dateiname dieser eingeschaltet ist

F:\Downloads\Downloads\500 Comics CCC CBR English\Isukani - Great Girl #01.cbr 
Verwandte Themen