2008-10-15 12 views
8

Tengo problemas para utilizar Perl grep() con una cadena que puede contener caracteres que se interpretan como cuantificadores de expresiones regulares.¿Hay una función Perl para convertir una cadena en una expresión regular para usar esa cadena como patrón?

I tiene el siguiente error cuando el patrón grep es "g ++" porque los símbolos '+' se interpretan como cuantificadores. Aquí está la salida por un programa que sigue:

1..3 
ok 1 - grep, pattern not found 
ok 2 - grep, pattern found 

Nested quantifiers in regex; marked by <-- HERE 
in m/g++ <-- HERE/at escape_regexp_quantifier.pl line 8. 

¿Hay un modificador que podría utilizar para indicar a grep que los cuantificadores se tendrán en cuenta, o hay una función que escaparía a los cuantificadores?

#! /usr/bin/perl 

sub test_grep($) 
{ 
    my $filter = shift; 
    my @output = ("-r-xr-xr-x 3 root  bin  122260 Jan 23 2005 gcc", 
        "-r-xr-xr-x 4 root  bin  124844 Jan 23 2005 g++"); 
    return grep (!/$filter/, @output); 
} 

use Test::Simple tests => 2; 

ok(test_grep("foo"), "grep, pattern not found"); 
ok(test_grep("gcc"), "grep, pattern found"); 
ok(test_grep("g++"), "grep, pattern found"); 

PS: además de la cuestión respuesta anterior, celebro cualquier comentario sobre el uso de Perl en el anterior ya que todavía estoy aprendiendo. Gracias

Respuesta

27

La forma habitual es utilizar el indicador \Q escapar antes de que la variable, a decir Perl no a analizar el contenido como una expresión regular:

return grep (!/\Q$filter/, @output); 

La alteración de esta línea en sus rendimientos de código:

 
1..3 
ok 1 - grep, pattern not found 
ok 2 - grep, pattern found 
ok 3 - grep, pattern found 
+0

nota \ Q termina en \ E, probablemente debería asegurarse de que \ E en el contenido se haya escapado. – Hasturkun

+0

No necesita - \ E en el patrón * interpolado * no causa problemas. – hexten

15

creo que busca quotemeta

+0

Sí, thas fue el término que me perdí, gracias. – philant

8

además de la pregunta de respuesta anterior, w Agradezco cualquier comentario sobre el uso de Perl en lo anterior, ya que todavía estoy aprendiendo. Gracias

Te aconsejo que no uses prototipos (($) después de test_grep). Tienen sus usos, pero no para la mayoría de los casos y definitivamente no en este.

+0

¿puedes dar más detalles sobre esto?Nunca había visto ese consejo antes. – Alnitak

+0

Ver http://stackoverflow.com/questions/297034/why-are-perl-function-prototypes-bad – cjm

2

PD: además de la pregunta de respuesta arriba, doy la bienvenida a cualquier comentario sobre el uso de Perl en lo anterior como todavía estoy aprendizaje.

El mejor consejo que puedo dar consejos para Perl codificación en general es instalar Perl::Critic y utilizar el comando perlcritic en su código. Si no puede hacer eso, puede usar el on-line perl critic tool. Le será útil si tiene a mano una copia de Perl Best Practices, ya que Perl::Critic ya leyó el libro y le dará referencias a los números de página; sin embargo, aunque no tenga el libro, todavía puede encontrar comentarios ampliados en las secciones Perl::Critic documentation comenzando con Perl::Critic::Policy::.

2

Sugiero usar qr para crear objetos Regexp en lugar de cadenas en este caso de todos modos.

ok(test_grep(qr/foo/), "grep, pattern not found"); 
ok(test_grep(qr/gcc/), "grep, pattern found"); 
ok(test_grep(qr/g\+\+/), "grep, pattern found"); 

Entonces no necesita el escape \ Q. Aunque todavía puede usarlo:

ok(test_grep(qr/\Qg++/), "grep, pattern found"); 
Cuestiones relacionadas