2012-12-13 3 views
6

implementieren Ich versuche, einen ausführlichen regulären Ausdruck in Python (2.7) zu verwenden. Wenn es darauf ankommt, versuche ich es einfacher zu machen, den Ausdruck irgendwann in der Zukunft klarer zu verstehen. Weil ich neu bin, habe ich zuerst einen kompakten Ausdruck erstellt, um sicherzustellen, dass ich das bekommen habe, was ich wollte. HierWie ein ausführliches REGEX in Python

ist der kompakte Ausdruck:

test_verbose_item_pattern = re.compile('\n{1}\b?I[tT][eE][mM]\s+\d{1,2}\.?\(?[a-e]?\)?.*[^0-9]\n{1}') 

Es als

Hier erwartet funktioniert, ist der Verbose Ausdruck

verbose_item_pattern = re.compile(""" 
\n{1}  #begin with a new line allow only one new line character 
\b?  #allow for a word boundary the ? allows 0 or 1 word boundaries \nITEM or \n ITEM 
I  # the first word on the line must begin with a capital I 
[tT][eE][mM] #then we need one character from each of the three sets this allows for unknown case 
\s+  # one or more white spaces this does allow for another \n not sure if I should change it 
\d{1,2} # require one or two digits 
\.?  # there could be 0 or 1 periods after the digits 1. or 1 
\(?  # there might be 0 or 1 instance of an open paren 
[a-e]?  # there could be 0 or 1 instance of a letter in the range a-e 
\)?   # there could be 0 or 1 instance of a closing paren 
.*   #any number of unknown characters so we can have words and punctuation 
[^0-9]  # by its placement I am hoping that I am stating that I do not want to allow strings that end with a number and then \n 
\n{1}  #I want to cut it off at the next newline character 
""",re.VERBOSE) 

Das Problem ist, dass, wenn ich die ausführlichen Muster betreiben ich eine bekommen Ausnahme

Traceback (most recent call last): 
File "C:/Users/Dropbox/directEDGAR-Code-Examples/NewItemIdentifier.py", line 17, in <module> 
""",re.VERBOSE) 
File "C:\Python27\lib\re.py", line 190, in compile 
    return _compile(pattern, flags) 
File "C:\Python27\lib\re.py", line 242, in _compile 
raise error, v # invalid expression 
error: nothing to repeat 

Ich fürchte, das wird etwas albern sein, aber ich kann es nicht herausfinden. Ich nahm meine ausführlichen Ausdrücke und komprimierte sie Zeile für Zeile, um sicherzustellen, dass die kompakte Version die gleiche wie die ausführliche war.

Die Fehlermeldung besagt, dass nichts zu wiederholen ist?

+0

Sie benötigen eine Schrägstriche zu entkommen - sie sind nicht in die Regex-Engine zu machen, wie sie während der normalen Python-String Verarbeitungsphase umgewandelt sind. In der komprimierten Version funktionierte das nur deswegen. Siehe auch "rohe Zeichenkettenliterale" :-) – Cameron

+0

@Cameron danke Ich nahm an, dass, weil ich ein dreifaches Zitat verwendete, ich den Schrägstrichen nicht entkommen musste. Ich habe getan, was du gesagt hast, und jetzt bekomme ich ein unerwartetes Ende des Musters und ich sah Beispiele, wo sie den Backslashes nicht entkommen konnten oder ein r vor der Zeichenkette verwenden. – PyNEwbie

Antwort

9
  • Es ist eine gute Gewohnheit rohe Stringliterale zu verwenden, wenn regex Muster definieren. Viele Regex-Muster verwenden umgekehrte Schrägstriche und ein roher Zeichenfolgenliteral ermöglicht es Ihnen, einzelne umgekehrte Schrägstriche anstelle von zu schreiben, ob Python Ihren umgekehrten Schrägstrich so interpretiert, dass er eine andere Bedeutung hat (und zwei umgekehrte Schrägstriche verwenden muss) in diesen Fällen).

  • \b? ist keine gültige Regex. Dies bedeutet 0 oder 1 Wortgrenzen. Aber entweder hast du eine Wortgrenze oder du nicht. Wenn Sie eine Wortgrenze haben, haben Sie 1 Wortgrenze. Wenn Sie keine Wortgrenze haben, haben Sie 0 Wortgrenzen. Also würde \b? (wenn es gültiger Regex wäre) immer wahr sein.

  • Regex unterscheidet zwischen dem Ende einer Zeichenfolge und dem Ende einer Zeile. (A String kann aus mehreren Zeilen bestehen.)

    • \A Matches nur den Anfang einer Zeichenkette.
    • \Z entspricht nur dem Ende einer Zeichenfolge.
    • $ gleicht das Ende einer Zeichenfolge und auch das Ende einer Zeile im Modus RE.MULTILINE ab.
    • ^ stimmt den Anfang einer Zeichenfolge und auch den Anfang einer Zeile im Modus RE.MULTILINE ab.

import re 
verbose_item_pattern = re.compile(r""" 
    $   # end of line boundary 
    \s{1,2}  # 1-or-2 whitespace character, including the newline 
    I   # a capital I 
    [tT][eE][mM] # one character from each of the three sets this allows for unknown case 
    \s+   # 1-or-more whitespaces INCLUDING newline 
    \d{1,2}  # 1-or-2 digits 
    [.]?   # 0-or-1 literal . 
    \(?   # 0-or-1 literal open paren 
    [a-e]?  # 0-or-1 letter in the range a-e 
    \)?   # 0-or-1 closing paren 
    .*   # any number of unknown characters so we can have words and punctuation 
    [^0-9]  # anything but [0-9] 
    $   # end of line boundary 
    """, re.VERBOSE|re.MULTILINE) 

x = verbose_item_pattern.search(""" 
Item 1.0(a) foo bar 
""") 

print(x) 

Ausbeuten

<_sre.SRE_Match object at 0xb76dd020> 

(anzeigt, dass es eine Übereinstimmung)

+0

danke für deine Antwort. Es hat geholfen und ich habe ein paar nützliche Dinge gelernt. Ich habe das $ nicht verstanden, jetzt tue ich es und ich verstehe die MULTILINE-Flagge nicht, dass die Regex ohne sie nicht funktioniert (ich bekomme keine Übereinstimmungen), also scheint es etwas Nützliches zu sein, an dem ich deine Zeit schätze – PyNEwbie

1

Wie sagt in dem Kommentar, sollten Sie Ihren Backslash oder Raw-String verwenden, auch mit dreifaches Zitat.

verbose_item_pattern = re.compile(r""" 
...