Reemplazo de expresiones regulares para una gran cantidad de pares de reemplazo de búsqueda [cerrado]

Quiero poder realizar búsquedas a gran escala y reemplazar documentos para fines de normalización de texto.

Por ejemplo:

  1. Encuentra todos los usos de EE.UU., USA y reemplazar con Estados Unidos de America
  2. Encuentre todos los símbolos de unión (&) y reemplácelos con la palabra y

También quiero poder agregar nuevas reglas al sistema sin tener que cambiar ningún código. Por lo tanto, los pares de reemplazo de búsqueda se almacenan en un almacén de datos, lo que significa que cualquiera puede agregar, actualizar y eliminar las reglas.

He estado trabajando con el módulo Python re, que es bastante agradable e idealmente me gustaría pasar una lista de tuplas al subcomando para que luego revise cada una y haga los reemplazos. ¿Hay una mejor manera de hacer esto que no sea iterar sobre una lista de tuplas y luego crear una expresión regular para cada una? Es muy lento e ineficiente, especialmente con documentos grandes:

replacements = [
  r('USA','United States Of America'),
  (r'U\.S\.A','United States Of America'),
  (r'US of A', 'United States of America')]

for replacement in replacements:
  document = re.sub(replacement[0],replacement[1],document

preguntado el 22 de mayo de 12 a las 15:05

Esta pregunta no es realmente adecuada para el formato de preguntas y respuestas de SO. (StackOverflow no es un motor de recomendaciones) -

@Mark, hay una pregunta en alguna parte, sugiere volver a escribirla. -

Vale, he tenido en cuenta lo que has dicho y he intentado plantearlo como una pregunta. -

Bien, esta es una pregunta mucho más clara. -

Reemplazar ciegamente & con y es una idea terrible. Puede ser parte de nombres formales. ¿Debería "S&P 500" convertirse en "S and P 500"? -

3 Respuestas

Ninguno de sus ejemplos requiere expresiones regulares. ¿Por qué no probar el buen reemplazo de cuerdas?

replacements = [
    ('USA','United States Of America'),
    ('U\.S\.A','United States Of America'),
    ('US of A', 'United States of America')]

for replacement in replacements:
    document = document.replace(replacement[0], replacement[1])

Parece que sería lento, pero debe compararlo antes de descartar el enfoque. Python es bastante bueno en cosas como esta y los resultados pueden sorprenderte.

Si realmente necesita expresiones regulares, es probable que vea un gran impulso al compilarlas:

replacements = [
    (re.compile('USA'),'United States Of America'),
    (re.compile('U\.S\.A'),'United States Of America'),
    (re.compile('US of A'), 'United States of America')]

for pattern, replacement in replacements:
    document = pattern.sub(replacement, document)

Esto le ahorra a Python el esfuerzo de tener que volver a compilar esas expresiones regulares cada vez que las usa.

Si solo necesita expresiones regulares algunas veces, considere realizar dos pasadas por el documento: una con expresiones regulares y otra con reemplazo de cadena. O si necesita un pedido específico de reemplazos, podría tener algo como:

replacements = [
    (re.compile('USA'),'United States Of America'),
    ('foo', 'bar'),
    (re.compile('U\.S\.A'),'United States Of America'),
    ('spam', 'eggs'),
    (re.compile('US of A'), 'United States of America')]

for pattern, replacement in replacements:
    try:
        document = pattern.sub(replacement, document)
    except AttributeError:
        document = document.replace(pattern, replacement)

contestado el 22 de mayo de 12 a las 16:05

El uso de string.replace estaría bien si no desea mantener el caso del texto original, ya que no le permite ignorar el caso como puede con una expresión regular. Por lo tanto, tendría que escribir en mayúsculas o minúsculas el cuerpo del texto y también los términos que está buscando, lo que afecta la salida. - marca unsworth

Echa un vistazo a Google Refine.

Google Refine, una poderosa herramienta para trabajar con datos desordenados

http://code.google.com/p/google-refine/

contestado el 22 de mayo de 12 a las 15:05

Tengo un archivo de culo grande con 6 MB de texto. Es una compilación de varios archivos del Proyecto Gutenberg.

Intentando esto:

reps = [
  (r'\bthousand\b','>>>>>1,000<<<<<'),
  (r'\bmillion\b',">>>>>1e6<<<<<"),
  (r'\b[Hh]undreds\b',">>>>>100's<<<<<"),
  (r'\bSherlock\b', ">>>> SHERLOCK <<<<")
  ]

t1=time.time()
out=[]  
rsMade=0
textLength=0
NewTextLen=0
with open('big.txt') as BigAssF:
    for line in BigAssF:
        textLength+=len(line)
        for pat, rep in reps:
            NewLine=re.subn(pat,rep,line)     

        out.append(NewLine[0])
        NewTextLen+=len(NewLine[0])
        rsMade+=NewLine[1]

print 'Text Length: {:,} characters'.format(textLength)
print 'New Text Length: {:,} characters'.format(NewTextLen)     
print 'Replacements Made: {}'.format(rsMade)     
print 'took {:.4} seconds'.format(time.time()-t1) 

Imprime:

Text Length: 6,488,666 characters
New Text Length: 6,489,626 characters
Replacements Made: 96
took 2.22 seconds

Lo que me parece adecuadamente rápido.

Es posible que tenga algunos problemas con su línea de código:

document = re.sub(replacement[0],replacement[1],document

si eso no es un error tipográfico.

¿Qué tan rápido esperas que sea?

contestado el 22 de mayo de 12 a las 18:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.