2008-10-27 19 views
29

Ich entwickle einen Algorithmus zum Parsen einer Zahl aus einer Reihe von kurzen Strings. Diese Strings sind etwas regulär, aber es gibt ein paar verschiedene allgemeine Formen und einige Ausnahmen. Ich versuche, eine Reihe von Regexes zu erstellen, die mit den verschiedenen Formen und Ausnahmen umgehen; Ich werde sie nacheinander anwenden, um zu sehen, ob ich ein Match bekomme.Eine optionale Teilzeichenfolge in einer Regex anpassen

Eine dieser Formen geht ungefähr so:

X (Y) Z 

Wo:

  • X ist eine Zahl, die ich aufnehmen möchten.
  • Z ist statischer, vordefinierter Text. es ist im Grunde, wie ich feststelle, ob diese bestimmte Form anwendbar ist oder nicht.
  • Y ist eine Zeichenfolge mit unbekannter Länge und Inhalt, umgeben von Klammern.

Auch: Y ist optional; es scheint nicht immer in einem String mit Z und X. Also, ich möchte von all diesen Strings, die Zahlen extrahieren können:

  • 10 Z
  • 20 (foo) Z
  • 30 (bar) Z

Gerade jetzt, ich habe einen regulären Ausdruck, der die erste wird erfassen:

([0-9]+) +Z 

Mein Problem ist, dass ich weiß nicht, wie zu konstruieren Eine Regex, die genau dann zu einer Reihe von Zeichen passt, wenn sie in runde Klammern eingeschlossen sind. Kann dies in einem einzigen Regex gemacht werden?

Antwort

46
(\d+)\s+(\(.*?\))?\s?Z 

Beachten Sie die entkam Klammern und das? (Null oder einmal) Quantifizierer. Jede der Gruppen, die Sie nicht erfassen möchten, kann (?: Nicht-Capture-Gruppen) sein.

Ich stimme den Räumen zu. \ s ist dort eine bessere Option. Ich habe auch den Quantifizierer geändert, um sicherzustellen, dass zu Beginn Ziffern vorhanden sind. Was Zeilenumbrüche betrifft, hängt das vom Kontext ab: Wenn die Datei zeilenweise analysiert wird, ist das kein Problem. Eine weitere Möglichkeit ist, den Anfang und das Ende der Zeile zu verankern (fügen Sie ein^an der Vorderseite und ein $ am Ende hinzu).

+0

Die Räume sind statisch. Ersetzen Sie sie mit \ s + –

+0

oder legen Sie eine davon in die()? –

+0

Beachten Sie, dass, wenn die Regex \ n mit erfasst. oder wenn es mehrere Instanzen in einer Zeile gibt, sollte dies nicht gierig sein: (\ d *) (\ (. *? \))? Z – eyelidlessness

2

Versuchen Sie folgendes:

X (\(Y\))? Z 
7

Sie dies tun können:

([0-9]+) (\([^)]+\))? Z 

Dies wird nicht mit verschachtelten Pars für Y arbeiten, aber. Die Verschachtelung erfordert eine Rekursion, die nicht mehr streng regulär (sondern kontextfrei) ist. Moderne Regexp-Engines können damit noch umgehen, wenn auch mit einigen Schwierigkeiten (Rückverweise).

+1

Glücklicherweise glaube ich nicht, dass ich verschachtelte Parens behandeln muss. –

14

Dies sollte funktionieren:

es
^\d+\s?(\([^\)]+\)\s?)?Z$ 

nicht getestet zwar, aber lassen Sie mich Ihnen den Abbau geben, so dass, wenn es irgendwelche Fehler verlassen sollten sie ziemlich einfach zu finden sein:

zuerst der Anfang:

^ = beginning of string 
\d+ = one or more decimal characters 
\s? = one optional whitespace 

Dann ist dieser Teil:

(\([^\)]+\)\s?)? 

Ist eigentlich:

(.............)? 

, die die folgenden Inhalte optional macht, nur dann, wenn es

\([^\)]+\)\s? 

\(= an opening bracket 
[^\)]+ = a series of at least one character that is not a closing bracket 
\) = followed by a closing bracket 
\s? = followed by one optional whitespace 

Und das Ende besteht aus

Z$ 

Wo

vollständig

existiert
Z = your constant string 
$ = the end of the string 
Verwandte Themen