2016-11-08 5 views
1

Ich habe eine Reihe von Textdateien zu analysieren, die möglicherweise keine Sammlung von Headern enthalten, und dann Zeilen von Daten oder Kommentar unterhalb dieser Überschrift. Allen Kopfgruppen wird ein doppelter Zeilenumbruch vorangestellt.Wie kann regulärer Ausdruck eine leere Zeichenfolge zurückgeben

Ich bin auf der Suche nach einem regulären Ausdruck, der eine leere Zeichenfolge zurückgibt, wenn eine Kopfzeile unmittelbar gefolgt von einem doppelten Zeilenumbruch angezeigt wird. Ich muss unterscheiden, ob ein Dokument diesen Header ohne Inhalt hat oder diesen Header überhaupt nicht hat.

Zum Beispiel, hier sind Teile von zwei Dokumente:

Dogs 
Spaniel 
Beagle 

Birds 
Parrot 

und

Dogs 

Amphibians 
Frogs 
Salamanders 

ich einen regulären Ausdruck möchte die Spaniel\nBeagle in dem ersten Dokument, und eine leere Zeichenfolge für die zweite zurückkehren .

Die nächste, die ich finden konnte, ist (in Python-Syntax) expr = re.compile("Dogs(.+?|)?\n\n, re.DOTALL). Dies gibt den richtigen Wert für den ersten zurück, aber im zweiten Fall gibt es zurück. Das zweite Fragezeichen und die Pipe tun nicht, was ich mir erhofft hatte.

Ich handle dies durch Programm Logik jetzt, Suche nach Dogs\n\n und nur Inhalte, wenn diese Regex nicht gefunden wird, aber es ist unbefriedigend, weil nichts das Gefühl von einem einzigen regulären Ausdruck die Arbeit macht.

Also: Gibt es eine Regex, die dem zweiten Dokument entspricht und "" zurückgibt?

+2

Verwendung: 'expr = re.compile (. R'Dogs * \ n \ n ')' – anubhava

+0

Guter Gott, war ich es jemals Grübeln. Vielen Dank! – prooffreader

+0

"Nichts geht über das Gefühl, dass ein einzelner regulärer Ausdruck die Aufgabe erfüllt.": Es ist eine naive Überzeugung. –

Antwort

0

Problem

Ihr Dogs(.+?|)?\n\n Muster passt das Wort Dogs beliebigen Stelle im Dokument, versucht dann, optional (als eine leere Alternative |) ist) mit irgendeinem 1 oder mehr (wegen +? quantifier) Zeichen, aber so wenig wie möglich (seit +? ist ein Lazy Quantor), bis zu den ersten 2 Zeilenumbrüche.

Das heißt, die Regex entweder übereinstimmt Dogs nur, wenn es keine Doppel Neuzeilensymbole irgendwo im Text weiter, oder es wird jeden Text greift dort bis zu dem ersten Doppel Neuzeilensymbole ist, weil die .+? 1 Newline verbrauchen, und der Musterteil \n\n kann die 2 Zeilenumbrüche nach nicht finden.

Lösung

Sie können einen *? quantifier von +? ein, damit passenden null oder mehr Zeichen verwenden statt. Die Dogs(.*?)\n\n finden Dogs, alle 0+ Zeichen so wenige wie möglich, bis zum ersten \n\n, auch diejenigen, die direkt nach erscheinen.

Optimierung:

Wenn Sie verarbeiten sehr lange Strings, und wenn die Dogs am Anfang einer Zeile angezeigt werden, können Sie eine abgerollt Regex verwenden, da .*? bekannt ist regex Ausführung mit längeren Eingaben zu verlangsamen.

Verwenden

expr = re.compile(r"^Dogs(.*(?:\n(?!\n).*)*)", re.MULTILINE) 

Siehe regex demo

Grundsätzlich wird es passen

  • ^ - Anfang einer Zeile
  • Dogs-Dogs Teilzeichenfolge
  • (.*(?:\n(?!\n).*)*) - Gruppe 1 Capturing:
    • .* - null oder mehr Zeichen andere als Zeichen Zeilenumbruch (wie der re.DOTALL Modifikator nicht verwendet wird)
    • (?:\n(?!\n).*)* - null oder mehr Sequenzen von:
      • \n(?!\n) - a newline nicht mit einem anderen newline gefolgt
      • .* - null oder mehr Zeichen außer Zeilenumbruch Zeichen
Verwandte Themen