2017-02-15 1 views
0

Ich benutze Python Regex, um Muster mit Strings zu vergleichen und stellte ein Problem mit der Benennung von Gruppen basierend auf mehreren Vorlagen.Python Regex - selektives Benennen von Gruppen mit '|' ('oder' in Regex)

Wenn vereinfacht wird es ein Problem mit dem Schreiben sein;

pattern = r'(?P<one>1)|(?P<one>one)' 
string = 'one' 
re.match(pattern, string).groupdict() 

Ich möchte {'one': 1} oder {'one': 'one'} als Ausgang haben. Dies erhöht jedoch den Fehler;

error: redefinition of group name 'one' as group 2; was group 1 at position 15 

Ein konkreteres Beispiel: Ich habe eine Liste von Strings, die jeweils Zeichenfolge enthält;

  • Präfix wie 'Hallo'
  • das Geschlecht der Person, und
  • ihren/seinen Geburtstag

wie folgt;

['hello F 10/Feb', 'hello Jan/12 M', 'hi F Feb 15', ...] 

und so weiter.

Sie schienen eine Vielfalt zu haben, aber alle folgen einer der Vorlagen;

  • Präfix + [Leerzeichen] + Geschlecht + [Leerzeichen] + Tag + '/' + Monat
  • Präfix + [Leerzeichen] + Monat + '/' + Tag + [Leerzeichen] + geschlechts
  • Präfix + [Leerzeichen] + Geschlecht + [Leerzeichen] + Monat + [Leerzeichen] + Tag

so dachte ich an einen regulären Ausdruck verwenden und sie in einem Wörterbuch enthalten von re.match() verwenden.

Als Anfang habe ich eine Liste von Templates in Regex geschrieben.

template = [ 
r'((?P<gender>[FM]) (?P<day>\d+)/(?P<month>\d+))', 
r'((?P<month>.+)/(?P<month>\d+) (?P<gender>[FM]))', 
r'((?P<gender>[FM]) (?P<month>.+)/(?P<day>\d))',] 

Hier habe ich entfernt, um den Teil Grüße, da es nie Position es ändert und weil ich wollte das Präfix Teil als Variable prefix für Usability Zwecke halten.

Dann habe ich versucht, sie mit einem '|' wie diese die Regex Form in einer angeschlossenen String zu machen

prefix + r'|'.join(template) 

beizutreten.

Wenn ich jedoch versuchte, es mit Regex zu vergleichen, hatte ich den Fehler für die Neudefinition.


Ich weiß, dass es von

for i in template: 
    re.match(prefix + i, string) 

Art der Sache getan werden könnte, aber wenn möglich, möchte ich in einer Linie, die die Musterkette halten.

Ist das möglich?

(ich benutze Python 3.5.2 | Anaconda 4.2.0 (64-bit))

+0

Dies ist in einigen Regex-Engines möglich, die Verzweigungsrücksetzgruppen (z. B. PCRE) unterstützen, aber leider nicht in "re". Sollte vom PyPi Regex Modul gemäß Doc. Die Syntax wäre dann '(? | (? P 1) | (? P eins)) '. –

+0

vielen dank! Übrigens, gibt es einen Grund, dass das Standardre-Modul diese Art des Schreibens nicht unterstützt? oder ist es einfach nicht vorgeschlagen. – Allosteric

+0

Es wird vom re-Modul nicht unterstützt. Ich weiß nicht, warum Entwickler das Modul auf diese Weise implementieren wollten. –

Antwort

0

Es ist möglich, aber nicht mit dem Standard-Modul re. Die Funktion, nach der Sie suchen, ist eine Gruppe zum Zurücksetzen von Verzweigungen, mit der Sie Gruppen für verschiedene Alternativen neu definieren können. Dies kann sowohl für nummerierte Gruppen als auch für benannte Gruppen verwendet werden. Um es in Python zu verwenden, können Sie das PyPi Regex module verwenden.

Allgemeine Syntax ist (?|(.)|(.)) wobei beide Erfassungsgruppen mit 1 nummeriert sind, da sie in verschiedenen Alternationen auftreten. Dasselbe kann für benannte Gruppen verwendet werden, sodass Ihr Beispiel als (?|(?P<one>1)|(?P<one>one)) geschrieben werden könnte.

Siehe demo on regex 101.

Hinweis: Dies ist ein PCRE-Muster, es gibt Unterschiede zwischen PCRE und dem Regex-Modul, aber die gezeigten Funktionen werden von beiden geteilt.