2011-03-16 11 views
5

Estoy tratando de dividir las oraciones en inglés correctamente, y se me ocurrió con la expresión regular profano a continuación:¿Por qué no es un patrón de ancho fijo?

(?<!\d|([A-Z]\.)|(\.[a-z]\.)|(\.\.\.)|etc\.|[Pp]rof\.|[Dd]r\.|[Mm]rs\.|[Mm]s\.|[Mm]z\.|[Mm]me\.)(?<=([\.!?])|(?<=([\.!?][\'\"])))[\s]+?(?=[\S])' 

El problema es, Python mantiene elevando el siguiente error:


Traceback (most recent call last): 
    File "", line 1, in 
    File "sp.py", line 55, in analyze 
    self.sentences = re.split(god_awful_regex, self.inputstr.strip()) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/re.py", line 165, in split 
    return _compile(pattern, 0).split(string, maxsplit) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/re.py", line 243, in _compile 
    raise error, v # invalid expression 
sre_constants.error: look-behind requires fixed-width pattern 

¿Por qué es esto no es una expresión regular válida de ancho fijo? No estoy usando ningún carácter repetitivo (* o +), solo |


EDITAR @Anomie resolvió el problema - gracias una tonelada! Desafortunadamente, no puedo hacer el nuevo equilibrio de expresión:

(?<!(\d))(?<![A-Z]\.)(?<!\.[a-z]\.)(?<!(\.\.\.))(?<!etc\.)(?<![Pp]rof\.)(?<![Dd]r\.)(?<![Mm]rs\.)(?<![Mm]s\.)(?<![Mm]z\.)(?<![Mm]me\.)(?:(?<=[\.!?])|(?<=[\.!?][\'\"\]))[\s]+?(?=[\S]) 

es lo que tengo ahora. El número de ('s coincide con el número de (' s, sin embargo:?

>>> god_awful_regex = r'''(?<!(\d))(?<![A-Z]\.)(?<!\.[a-z]\.)(?<!(\.\.\.))(?<!etc\.)(?<![Pp]rof\.)(?<![Dd]r\.)(?<![Mm]rs\.)(?<![Mm]s\.)(?<![Mm]z\.)(?<![Mm]me\.)(?:(?<=[\.!?])|(?<=[\.!?][\'\"\]))[\s]+?(?=[\S])''' 
>>> god_awful_regex.count('(') 
17 
>>> god_awful_regex.count(')') 
17 
>>> god_awful_regex.count('[') 
13 
>>> god_awful_regex.count(']') 
13 

¿Alguna idea más

+0

No tengo idea, pero quizás porque [Pp] rof = 4 caracteres mientras [Mm] rs = 3 caracteres? – orlp

+0

Acerca del paréntesis desbalanceado: A simple vista, el problema parece ser que cerca del final de su expresión regular, ha escapado por error del corchete de cierre de una clase de caracteres, haciendo que los paréntesis de cierre sean parte de la clase en lugar de su función real . También ha escapado más de lo necesario en otros casos. Pruebe esto: 'r '' '(?

+0

Además, es posible que desee simplificar su expresión regular haciendo que no distinga entre mayúsculas y minúsculas (compilarla con la opción 're.I'). –

Respuesta

11

consideran este subexpresión:

(?<=([\.!?])|(?<=([\.!?][\'\"]))) 

El lado izquierdo de la | es un personaje, mientras que el tamaño correcto es cero. También tiene el mismo problema en su aspecto negativo más grande, podría ser 1, 2, 3, 4 o 5 caracteres.

Lógicamente, un aspecto negativo detrás de (?<!A|B|C) debe ser equivalente a una serie de (?<!A)(?<!B)(?<!C) mira atrás. Una mirada positiva detrás de (?<=A|B|C) debería ser equivalente a (?:(?<=A)|(?<=B)|(?<=C)).

-1

Parece que podría estar usando los chacters repetición cerca del final:

[\s]+? 

A menos que estoy leyendo mal.

ACTUALIZACIÓN

O barra vertical como nightcracker se menciona, y la primera respuesta a esta pregunta parece confirmar: determine if regular expression only matches fixed-length strings

+0

Sí, pero dado que es DESPUÉS del aspecto detrás, no debería afectarlo. – orlp

+0

Como Nightcracker dijo que la barra vertical "O" permite que se concuerden cadenas de diferentes longitudes, ¿quizás eso cuenta? – ctcherry

+0

Según la primera respuesta a esta pregunta: http://stackoverflow.com/questions/3627570/determine-if-regular-expression-only-matches-fixed-length-strings la barra vertical podría ser la culpable – ctcherry

0

Esto no responde a su pregunta. Sin embargo, si desea dividir un texto en oraciones, es posible que desee echar un vistazo a nltk, que incluyen junto a muchas otras cosas un PunktSentenceTokenizer. Aquí está un cierto ejemplo tokenizer:

""" PunktSentenceTokenizer 

A sentence tokenizer which uses an unsupervised algorithm to build a model 
for abbreviation words, collocations, and words that start sentences; and then 
uses that model to find sentence boundaries. This approach has been shown to 
work well for many European languages. """ 

from nltk.tokenize.punkt import PunktSentenceTokenizer 

tokenizer = PunktSentenceTokenizer() 
print tokenizer.tokenize(__doc__) 

# [' PunktSentenceTokenizer\n\nA sentence tokenizer which uses an unsupervised 
# algorithm to build a model\nfor abbreviation words, collocations, and words 
# that start sentences; and then\nuses that model to find sentence boundaries.', 
# 'This approach has been shown to\nwork well for many European languages. '] 
Cuestiones relacionadas