2008-10-15 9 views
8

J'ai du mal à utiliser Perl grep() avec une chaîne qui peut contenir des caractères qui sont interprétés comme des quantificateurs d'expressions régulières.Existe-t-il une fonction Perl pour transformer une chaîne en expression rationnelle afin d'utiliser cette chaîne comme modèle?

J'ai l'erreur suivante lorsque le modèle grep est "g ++" car les symboles '+' sont interprétés comme des quantificateurs. Voici la sortie pour le programme qui suit:

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. 

est-il un modificateur je pourrais utiliser pour indiquer grep que les quantificateurs doivent être ignorées, ou est-il une fonction qui échapperait quantificateurs?

#! /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: en plus de la question de réponse ci-dessus, je me réjouis des commentaires sur l'utilisation de Perl dans ce qui précède que je suis encore à apprendre. Merci

Répondre

27

La méthode standard consiste à utiliser l'indicateur d'échappement \Q avant votre variable, de dire Perl pour analyser le contenu comme une expression régulière:

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

Modifier cette ligne dans vos rendements de code:

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

note \ Q se termine à \ E, devrait probablement s'assurer que \ E dans le contenu est échappé. – Hasturkun

+0

Vous n'avez pas besoin de - \ E dans le motif * interpolé * ne cause aucun problème. – hexten

15

Je pense que vous cherchez quotemeta

+0

Oui, c'était le terme que j'ai manqué, merci. – philant

8

en plus à la question de réponse ci-dessus, je w Elcome tout commentaire sur l'utilisation de Perl dans le ci-dessus que je suis encore en train d'apprendre. Merci

Je vous conseille de ne pas utiliser de prototypes (($) après test_grep). Ils ont leurs usages, mais pas pour la plupart des cas et certainement pas dans celui-ci.

+0

pouvez-vous élaborer à ce sujet?Je n'ai jamais vu ce conseil auparavant. – Alnitak

+0

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

2

PS: en plus de la question de la réponse ci-dessus, je me réjouis des commentaires sur l'utilisation de Perl dans ce qui précède que je suis encore à apprendre .

Le meilleur conseil que je peux donner des conseils de codage Perl en général est d'installer Perl::Critic et utilisez la commande perlcritic sur votre code. Si vous ne pouvez pas faire cela, vous pouvez utiliser le on-line perl critic tool. Il sera utile si vous avez une copie de Perl Best Practices pratique, puisque Perl::Critic a déjà lu le livre et vous donnera des références aux numéros de page, mais même si vous n'avez pas le livre autour, vous pouvez toujours trouver des commentaires étendus dans les sections Perl::Critic documentation avec Perl::Critic::Policy::.

2

Je suggère d'utiliser qr pour créer des objets Regexp plutôt que des chaînes dans ce cas de toute façon.

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"); 

Ensuite, vous n'avez pas besoin de l'échappement \ Q. Bien que vous puissiez toujours l'utiliser:

ok(test_grep(qr/\Qg++/), "grep, pattern found"); 
Questions connexes