2013-09-02 8 views
5

Ich habe mit Python Regex für eine Weile kämpfen versucht, Absätze in einem Text übereinstimmen, aber ich war nicht erfolgreich. Ich muss die Anfangs- und Endpositionen der Absätze erhalten.Wie passen einen Absatz mit Regex

Ein Beispiel für einen Text:

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod 
tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At 
vero eos et accusam et justo duo dolores et ea rebum. 

Stet clita kasd gubergren, 
no sea takimata sanctus est Lorem ipsum dolor sit amet. 

Ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod 
tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At 
vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, 
no sea takimata sanctus est Lorem ipsum dolor sit amet. 

In diesem Beispielfall würde ich mag separat die Absätze alle mit Lorem, Stet und Ipsum bzw. (ohne Leerzeilen) beginnen lassen. Hat jemand eine Idee, wie man das macht?

+1

Gibt es einen Grund, warum Sie wollen, dies zu tun mit Regex? Für etwas so Einfaches wie das Aufteilen von durch Doppel-Zeilenumbruch getrennten Absätzen könnten Sie einfach 'paragraph.split ('\ n \ n')' –

+0

verwenden. Ich interessiere mich für die Anfangs- und Endpositionen der Absätze, nicht für die tatsächlichen Zeichenfolgen. Ich hätte das erwähnen sollen. –

Antwort

3

Sie auf zwei Newline wie folgt aufteilen:

paragraphs = re.split(r"\n\n", DATA) 

Edit: die Absätze zu erfassen, wie übereinstimmt, so dass Sie ihre Start- und Endpunkte bekommen, dies tun:

for match in re.finditer(r'(?s)((?:[^\n][\n]?)+)', DATA): 
    print match.start(), match.end() 

# Prints: 
# 0 214 
# 215 298 
# 299 589 
+0

Wie kann ich das verwenden, um ein Match-Objekt zu erhalten? –

2

Split zu verwenden ist eine Art und Weise, Sie so mit regulären Ausdrücken wie dies auch tun können:

paragraphs = re.search('(.+?\n\n|.+?$)',TEXT,re.DOTALL) 

Die .+? ist eine träge Übereinstimmung, sie wird der kürzesten Teilzeichenfolge entsprechen, die die gesamte Regex übereinstimmen lässt. Andernfalls wird nur die gesamte Zeichenfolge abgeglichen.

Also im Grunde hier wollen wir eine Folge von Zeichen finden (.+?), die durch eine Leerzeile endet (\n\n) oder das Ende der Zeichenkette ($). Das Flag re.DOTALL passt den Punkt auch an Newline an (wir möchten auch einen Absatz, der aus drei Zeilen ohne Leerzeilen besteht) abgleichen

+0

Danke für Ihre Antwort. Beachten Sie jedoch, dass dieses Muster auch mit leeren Zeilen übereinstimmt, was nicht korrekt ist. –

0

Was ist das Newline-Symbol? Lassen Sie uns das Neuzeilensymbol annehmen, ist ‚\ r \ n‘, wenn Sie die Absätze, beginnend mit Lorem übereinstimmen soll, können Sie wie folgt tun:

pattern = re.compile('\r\nLorem.*\r\n') 
str = '...' # your source text 
matchlist = re.findall(pattern, str) 

Der Match enthält alle paragragh mit Lorem starten. Und die anderen beiden Wörter sind gleich.

+0

Das Newline-Zeichen in Python ist normalerweise \ n. Und dein Muster funktioniert nicht. –

+0

Sorry, ich habe einen Fehler gemacht. Sie können dies versuchen: 'p = re.compile ('^ Lorem. * \ N') matchlist = re.findall (p, s)' Dann erhalten Sie die Liste der Absätze beginnen mit Lorem –

0

Versuchen

^(.+?)\n\s*\n 

oder

^(.+?)\r\n\s*\r\n 

nur nicht vergessen, zusätzliche neue Zeile am Textende anhängen

0

Ich habe versucht, die empfohlene RegEx mit dem Standard-Java RegEx-Engine zu verwenden . Das gab mir mehrere Male eine StackOverflowException, also habe ich die RegEx am Ende neu geschrieben und ein wenig mehr optimiert.

So ist diese Arbeit für mich in Java fein:

(?s)(.*?[^\:\-\,])(?:$|\n{2,}) 

Dies auch das Ende des Dokuments ohne neue Linien behandelt und versucht, Linien zu verketten, die mit endet ‚:‘, ‚-‘ oder ‚‘ zum nächsten Absatz.

Und zu vermeiden, dass Leerzeichen (Leerzeichen oder Tabs) bricht die oben beschriebene Funktion Hinter ich sie, bevor sie mit folgenden regex am Strippen:

(?m)[[:blank:]]+$