2011-05-21 20 views
5

que he visto este post anterior, sobre la correspondencia contra múltiples expresiones regulares How can I match against multiple regexes in Perl?¿Cómo puedo hacer coincidir contra varias expresiones regulares en Perl?

que estoy buscando la manera más rápida para que coincida con todos los valores contenidos en una matriz con un archivo muy grande (500 MB).

Los patrones se leen desde la entrada estándar y pueden contener caracteres especiales que deben utilizarse en la expresión regular (anclas, clases de personajes, etc.). La coincidencia debe realizarse cuando todos los patrones están contenidos en la fila actual.

Actualmente estoy usando un anidada para el ciclo, pero no estoy muy satisfecho con la velocidad ....

Gracias por sus sugerencias.

+3

¿Cómo se ha confirmado que la velocidad de los datos IO 500 MB no es el factor limitante? – Richard

+1

Como una simple optimización, asegúrese de que sus expresiones regulares que tienen más probabilidades de fallar se prueban _primero_. De esta forma, puede pasar al siguiente registro lo más rápido posible cuando detecta un error. – pjf

+2

Quizás debería mostrarnos algunos códigos y expresiones regulares, por lo que podríamos tener algo con lo que trabajar. Además, cualquier información sobre cómo se verá la entrada. – TLP

Respuesta

4

¿Usted intentó utilizar grep?

while($line=<>) { 
    if (scalar(grep($line=~/$_/,@regexps))==scalar(@regexps)) { 
     # ... All matched 
    } 
} 
+1

o simplemente 'if (! Grep {!} @List condición) {...}' – Dallaylaen

+0

gracias esta el código es simple y parece funcionar use 5.014; my @ regexps = qw (foo?bar {2} [Rr] en^este estéril $); my $ line = 'esta comida es bastante estéril'; if (escalar (grep ($ line = ~/$ _ /, @ regexps)) == escalar (@regexps)) { decir 'todo coincide'; }
else {dicen 'no todos igualada'} – user764169

8

Trate Regexp::Assemble como se sugiere en la entrada que está vinculada y compararlo con un enfoque iterativo como grep. Regexp :: Assemble debería producir la solución más rápida ya que Perl puede optimizar las expresiones regulares unidas en lugar de escanear toda la línea para cada una. Como no conoce su entrada de antemano, ymmv.

¿Qué versión de Perl que está utilizando afectará el rendimiento. 5.10 introdujo muchas optimizaciones para exactamente este propósito (ver "tries"). Uno de los casos de uso más importantes son los escáneres de spam como SpamAssassin que construyen una gran expresión regex de todos los patrones que buscan, al igual que Regexp :: Assemble.

Finalmente, dado que su entrada es tan grande, puede valer la pena ensamblar la expresión regular en un archivo y luego ejecutar grep -P -f $regex_file $big_file. -P dice grep para usar expresiones regulares compatibles con Perl. El archivo se usa para evitar límites de cotización de shell o tamaño de comando. grep puede volar las puertas de Perl.

Al final, vas a tener que hacer la evaluación comparativa.

+1

El problema con Regexp :: Ensamble es que los retornos "éxito" cuando coincide con una condición, que necesitan un partido en todas las condiciones. Creo que es más rápido continuar usando el ciclo anidado "para". Estoy usando Perl 5.14 (a través de la fantástica perlbrew). – user764169

Cuestiones relacionadas