2009-11-15 2 views
1

J'utilise Regexp::Assemble dans mon projet, mais je ne comprends pas pourquoi ce petit échantillon ne fonctionne pas:Pourquoi Regexp :: Assemble échoue-t-il avec ces simples regexps?

#!/usr/bin/perl 

use strict; 
use warnings; 

use Regexp::Assemble; 

my $re1 = "(run (?:pre|post)flight script for .+)"; 
my $re2 = "((?:Configu|Prepa)ring volume .+)"; 

my $ra = Regexp::Assemble->new; 
$ra->add($re1); 
$ra->add($re2); 
my $global = $ra->re; 

print "GLOBAL: $global\n"; 

1; 

Je suis cette erreur:

Unmatched (in regex; marked by <-- HERE in m/(<-- HERE ?:(run (?:pre|post)flight script for|((?:Configu|Prepa)ring volume) .+)/ at /usr/share/perl5/Regexp/Assemble.pm line 1003. 

Edit: Si je juste imprimer le Regexp (AD- $> as_string) résultant je suis arrivé ceci:

GLOBAL: (?:(run (?:pre|post)flight script for|((?:Configu|Prepa)ring volume) .+) 

Il y a un ')' manquante ...

Répondre

2

Cela ressemble à un bug? Vous confondez le constructeur regex. Voyez comment il combine vos deux motifs et non apparentées entre parenthèses:

my $re1 =  "(run (?:pre|post)flight script for .+)"; 
my $re2 =          "((?:Configu|Prepa)ring volume .+)"; 

#   m/(?:(run (?:pre|post)flight script for|((?:Configu|Prepa)ring volume) .+)/ at... 

Essayez de supprimer l'ensemble supplémentaire de parenthèses de vos expressions rationnelles et voir si cela aide:

my $re1 = "run (?:pre|post)flight script for .+"; 
my $re2 = "(?:Configu|Prepa)ring volume .+"; 
+0

Oui, il fonctionne sans les parenthèses supplémentaires ... mais voici un exemple, je besoin de ces plus complexes dans regexps! – sebthebert

+0

Eh bien, cela répond à la question que vous avez écrite ... :) peut-être éditer votre question pour donner un exemple de façon plus compliquée? – Ether

+0

Ok, je devrais ajouter "et comment puis-je résoudre ce problème sans modifier mes expressions rationnelles" :) Une idée? – sebthebert

4

approche de l'éther semble comme un plan - Si vous regardez la documentation du module, il mentionne spécifiquement à surveiller:

add() ... il utilise une expression régulière naïve à la lex la chaîne qui peut être dupé [par] des expressions complexes (en particulier, il ne parviendra pas à la lex expressions parenthétiques imbriquées telles que ab (cd (ef)? gh) ij correctement). Si c'est le cas, la fin de la chaîne ne sera pas correctement segmentée et renvoyée en une longue chaîne.

+0

Je ne l'ai pas lu que dans ma première lecture ... :( – sebthebert

+0

Ok merci, vous avez répondu « pourquoi », mais je suis aussi intéressé par le «COMMENT PUIS-JE correctif :) – sebthebert

4

Je suis l'auteur de R :: A. Cette question revient tous les deux ans. L'idée est que vous ne voulez pas ajouter de motifs parenthèses complexes. Ajoutez plus de motifs plus simples, par ex.

run preflight script for .+ 
run postflight script for .+ 
Configuring volume .+ 
Preparing volume .+ 

N'essayez pas de faire le travail du module. Par exemple, votre regroupement prématuré a abouti à la fin .+ commune à tous les modèles qui ne sont pas factorisés en une occurrence dans l'expression rationnelle. Le résultat est que vous avez introduit backtracking inutile. Plus vous ajoutez de motifs, plus ce sera pire.

Calling add() dans un ordre différent produira le même modèle résultant (ou bien il est un bug que je voudrais savoir sur).

Sinon, vous pouvez pretokenise les modèles vous-même, et utiliser insert() pour insérer le motif lexèmes directement dans la structure interne utilisée pour Trie construire le modèle. (Ce sera beaucoup plus rapide, car la lexeur est très lente: elle consomme plus de la moitié du temps d'exécution pour assembler un motif).

+0

Quand j'Assemblez le dessus quatre modèles, j'obtiens '(?: run p (?: ost | re) script de vol pour le volume de la sonnerie | (?: Configu | Prepa). + '. Remarquez comment le module a hissé le 'p' hors de l'alternance (post | pré)? – dland