2017-07-24 1 views
0

Wenn eine Regex Suche in Python durchführen, selbst wenn re.MULTILINE nicht, wirdKann Pythons Regex daran gehindert werden, Zeilenumbrüche mit ' s' zu kreuzen?

aktiviert ist

Der Ausdruck A[\s]B gegen

A 
B 

entsprechen Da ein Newline \s übereinstimmt.

Neben der Aufspaltung der Zeichenkette in Zeilen und die Bearbeitung der einzelnen - Gibt es eine effiziente Möglichkeit, die Ausdrücke auf Zeilenumbrüche zu begrenzen?


Edit: Ich seine möglichen kennen [\t ] oder [^\S\r\n] zu verwenden, ist das Problem, das ich in diesem Fall nicht über die Eingabe steuern, Benutzer \s eingeben und werde es nicht erwarten, Linien spand. Ich bin nicht daran interessiert, den Benutzern zu sagen, dass sie falsch liegen, aus ihrer Sicht ist dies ein Fehler.

Also, wenn die Antwort ist "es kann nicht ohne Zeilenaufteilung getan werden" - so sei es.


Beachten Sie, dass die Verarbeitung einer Datei Zeile für Zeile in meinen Tests ungefähr doppelt so langsam ist.

+0

Fragen Sie, wie Sie nur * horizontale Leerzeichen * abgleichen können? –

+0

Ich denke schon, ja. – ideasman42

+0

Verwenden Sie '[^ \ S \ r \ n]' –

Antwort

0

Kurze Antwort ist nein, Pythons Regex kann nicht gemacht werden, so dass \s nicht übereinstimmen \n.

Sie können '\ n' in den Übereinstimmungen erkennen und diese überspringen.

def finditer_delimit_newlines(pattern, string, delimit_newlines=True): 
    matches = list(re.finditer(pattern, string)) 
    if not matches: 
     return [] 

    end = matches[-1].start() 
    newline_table = {-1: 0} 
    for i, m in enumerate(re.finditer(r'\n', string), 1): 
     offset = m.start() 
     newline_table[offset] = i 
     if offset > end: 
      break 

    for m in matches: 
     m_start = m.start() 
     m_end = m.end() 
     newline_offset = string.rfind('\n', 0, m_start) 
     newline_end = string.find('\n', m_end) 
     if delimit_newlines: 
      if ((newline_table[newline_offset] + 1) != 
       (newline_table[newline_end] 
       if newline_end != -1 else len(newline_table)) 
      ): 
       continue 
     yield m 


search = """A 
B 

A B""" 

import re 

for delimit_newlines in (False, True): 
    print("Test:", delimit_newlines) 
    for a in finditer_delimit_newlines(r'[A-Z]\s[A-Z]', search, delimit_newlines): 
     print(a) 

Dieser Test gibt

Test: False 
<_sre.SRE_Match object; span=(0, 3), match='A\nB'> 
<_sre.SRE_Match object; span=(5, 8), match='A B'> 
Test: True 
<_sre.SRE_Match object; span=(5, 8), match='A B'> 

bearbeiten, ein Spiel erfassen kann Zeilenumbrüche als Teil der regulären Leerzeichen, während seines möglich zu erkennen dies, könnte es einfacher Gebrauch sein ein ähnliches Verfahren nachlauf Das passt die Ergebnisse in begrenzten Bereichen erneut an, wenn neue Zeilen vorhanden sind.

0

Technisch \s ist nur eine Abkürzung für [ \t\r\n\f]

was bedeutet, dass alle ([^\\]|^)(\\\\)*\\s mit $1$2[ \t\r\n\f] auf dem RegexMuster ersetzen laufen keine Wirkung. (muss nicht maskiert \s) Also TECHNISCH können Sie einfach die oben genannten vereinfachen, so dass die Zeichenklasse \s nur [ \t] ist. Wie andere bereits gesagt haben, ist die Änderung der Funktionalität von Regex, ohne dem Endbenutzer zu sagen, sehr sehr schlecht, und es wäre wahrscheinlich einfacher zu erklären/implementieren, alle Leerzeichen in der Regex durch die Zeichenklasse [ \t] zu ersetzen (z. B.) Dies ist eine kleinere Änderung des Basisregelsatzes. Wenn der Endbenutzer aus einem bestimmten Grund denkt, \s könne keine neuen Zeilen erfassen, sollten Sie die Datei wahrscheinlich genauso analysieren, wie der Endbenutzer erwartet, sodass die Codelogik der Endbenutzerlogik entspricht.

Verwandte Themen