2008-11-14 6 views
5

Je vais avoir du mal à déterminer quels caractères doit être échappé lors de l'utilisation de qr Perl construction {}Quels caractères dois-je échapper dans une regex pré-compilée Perl?

je tente de créer une regex précompilés plusieurs lignes pour le texte qui contient une myriade de personnages normalement évadés (# *.>: []) et contient également une autre regex précompilée. De plus, je dois correspondre aussi strictement que possible à des fins de test.

my $output = q{# using defaults found in .config 
* 
* 
Options: 
    1. opt1 
> 2. opt2 
choice[1-2?]: }; 

my $sc = qr{(>|\s)}smx; 
my $re = qr{# using defaults found in .config 
* 
* 
Options: 
$sc 1. opt1 
$sc 2. opt2 
choice[1-2?]: }mx; 

if ($output =~ $re) { 
    print "OK!\n"; 
} 
else { 
    print "D'oh!\n"; 
} 

Erreur:

Quantifier follows nothing in regex; marked by <-- HERE in m/# using defaults found in .config 
* <-- HERE 
* 
Options: 
(?msx-i:(>|\s)) 1. opt1 
(?msx-i:(>|\s)) 2. opt2 
choice[1-2?]:/at ./so.pl line 14. 

tentative d'échapper aux résultats des astérisques dans un match échoué (D'oh sortie). Tenter d'échapper à d'autres caractères embêtants entraîne également une correspondance ratée. Je pourrais continuer à essayer différents combos de quoi échapper, mais il y a beaucoup de variations ici et j'espère que quelqu'un pourrait fournir un aperçu.

Répondre

14

Vous devez échapper le délimiteur pour qr //, et vous devez échapper tous les métacaractères regex que vous voulez utiliser comme littéraux. Si vous voulez que ceux-ci soient littéraux, vous devez leur échapper puisque le * est un quantificateur d'expressions rationnelles.

Votre problème ici est les différents indicateurs regex que vous avez ajoutés. Le/m ne fait rien car vous n'utilisez pas les ancres de début ou de fin de chaîne (^, $). Le/s ne fait rien car vous n'utilisez pas le caractère générique. métacaractère. Le/x rend tous les espaces dans votre regex insignifiants, et il transforme cette ligne avec le # dans un commentaire regex.

C'est ce que vous voulez, avec des drapeaux regex enlevés et les choses propres se sont échappés:

my $sc = qr{(>|\s)}; 

my $re = qr{# using defaults found in \.config 
\* 
\* 
Options: 
$sc 1\. opt1 
$sc 2\. opt2 
choice\[1-2\?]: }; 

Bien que Damian Conway dit aux gens dans Perl meilleures pratiques de toujours mettre ces options sur leurs regexes, vous voyez maintenant pourquoi il a tort. Vous devriez seulement les ajouter quand vous voulez ce qu'ils font, et vous devriez seulement ajouter des choses quand vous savez ce qu'ils font. :) Voici ce que vous pourriez faire si vous voulez utiliser/x. Vous devez échapper à n'importe quel espace littéral, vous devez indiquer les fins de ligne et vous devez échapper au caractère littéral #. Ce qui était lisible avant est maintenant un gâchis:

 
my $sc = qr{(>|\s)}; 
my $eol = qr{[\r\n]+}; 

my $re = qr{\# \s+ using \s+ defaults \s+ found \s+ in \s+ \.config $eol 
\*     $eol 
\*     $eol 
Options:    $eol 
$sc \s+ 1\. \s+ opt1 $eol 
$sc \s+ 2\. \s+ opt2 $eol 
choice\[1-2\?]: \s+ 
}x; 

if ($output =~ $re) { 
    print "OK!\n"; 
} 
else { 
    print "D'oh!\n"; 
} 
+0

Argh! Ma compréhension de ce que 's' et 'x' faisait était inverse de la réalité. D'où le 's' manquant de $ re. Mais oui, je blâme PbP ici aussi. :) –

+0

Le livre explique ce que les options font et pourquoi les utiliser ... vous ne pouvez pas vraiment blâmer le livre pour cela. :) –

+0

Je peux blâmer le livre. Il est dit "Toujours utiliser le drapeau/x" (p 236) et "Toujours utiliser le drapeau/m" (p 237).La recommandation de "Toujours" est erronée. –

7

Sonne comme ce que vous voulez vraiment est Expect, mais la chose que vous êtes le plus à la recherche immédiatement est l'opérateur quotemeta qui échappe à tous les caractères qui ont une signification particulière à une expression régulière.

Pour répondre à votre question directement (cependant), en plus du caractère unquote (dans ce cas }) dont vous avez besoin pour échapper au minimum, .[$()|*+?{\

+0

En fait, ceci est utilisé en conjonction avec Expect and Test :: More. Simplement réduisez le code pour des raisons d'exemples. –

2

Comme brian dit, vous devez échapper aux délimiteurs et regex métacaractères . Notez que lorsque vous utilisez qr//x (ce que vous êtes), vous devez également quitter les espaces blancs et # (qui est un marqueur de commentaire). Vous ne voulez probablement pas utiliser /x ici. Si vous voulez être sûr, peut échapper tout caractère non alphanumérique.

Questions connexes