2012-12-13 11 views
6

Sto cercando di utilizzare un'espressione regolare dettagliata in Python (2.7). Se è importante, sto solo cercando di rendere più facile tornare indietro e capire più chiaramente l'espressione in futuro. Poiché sono nuovo, per prima cosa ho creato un'espressione compatta per assicurarmi di ottenere ciò che volevo.Come implementare un REGEX in Python

Ecco l'espressione compatta:

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

Funziona come previsto

Qui è l'espressione Verbose

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) 

Il problema è che quando faccio funzionare il modello verbose ottengo un eccezione

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 

Ho paura che questo sia qualcosa di sciocco ma non riesco a capirlo. Ho preso le mie espressioni prolisse e l'ho compattato riga per riga per assicurarmi che la versione compatta fosse la stessa del verboso.

Il messaggio di errore indica che non c'è nulla da ripetere?

+0

È necessario sfuggire alle barre rovesciate: non lo fanno nel motore regex mentre vengono convertiti durante la normale fase di elaborazione delle stringhe Python. A causa di ciò, ha funzionato solo incidentalmente nella versione compressa. Inoltre, cerca "stringhe di stringhe raw" :-) – Cameron

+0

@Cameron, grazie, ho pensato che, poiché stavo usando una citazione tripla, non dovevo sfuggire alle barre. Ho fatto come hai detto e ora ho una fine inaspettata del pattern e ho visto esempi in cui non sono sfuggiti alle backslash o usare una r davanti alla stringa – PyNEwbie

risposta

9
  • È buona norma utilizzare stringhe prime nel definire espressioni regolari modelli. Un sacco di schemi di espressioni regolari utilizzano i backslash e l'utilizzo di un valore letterale stringa non elaborato consentirà di scrivere singole barre rovesciate anziché dovendosi preoccupare che Python interpreterà o meno il backslash in modo da avere un significato diverso (e dover utilizzare due barre rovesciate) in quei casi).

  • \b? non è valido regex. Questo sta dicendo i confini delle parole 0 o 1. Ma o hai un limite di parole o non lo fai. Se hai un limite di parole, hai un limite di 1 parola. Se non si dispone di un limite di parole, si avranno 0 limiti di parola. Quindi \b? sarebbe (se fosse una regex valida) sempre true.

  • Regex distingue tra la fine di una stringa e la fine di una linea. (Una stringa può essere costituito da più righe.) Solo

    • \A partite l'inizio di una stringa.
    • \Z corrisponde solo alla fine di una stringa.
    • $ corrisponde alla fine di una stringa, e anche fine di una linea in modalità re.MULTILINE.
    • ^ corrisponde l'inizio di una stringa, e anche all'inizio di una riga in modalità re.MULTILINE.

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) 

rendimenti

<_sre.SRE_Match object at 0xb76dd020> 

(che indica v'è una corrispondenza)

+0

grazie per la tua risposta. Ha aiutato e ho imparato alcune cose utili. Non ho capito il $, ora faccio e non capisco il flag MULTILINE la regex non funziona senza di esso (non sto ottenendo corrispondenze) quindi sembra che qualcosa di utile da colpire apprezzo il tuo tempo – PyNEwbie

1

Come dicono nei commenti si dovrebbe sfuggire la vostra barra rovesciata o utilizzare stringa elevata anche con citazione tripla.

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