2010-05-10 3 views
8

Je travaille sur une implémentation de moteur de recherche assez spécialisée en Perl, elle recherche (par regex) des documents spécifiquement délimités (un sous-ensemble de: punct:) les chaînes d'un fichier texte. Je fais les astuces d'indexation habituelles des moteurs de recherche, mais il y a un problème.Comment identifier les "jetons" (mauvais mot) d'une expression régulière

Certains des motifs d'expression rationnelle de recherche incluent, par nécessité, des délimiteurs utilisés dans le fichier. "Ok, je pense à moi-même," proximité de mot, alors ... facile "... et ce côté de l'équation est assez simple

L'astuce est que parce que les modèles de recherche sont des expressions régulières, je n'ai pas Je ne peux pas déterminer facilement les mots spécifiques que je devrais rechercher dans les données indexées (pensez à "diviser" si nous parlons de chaînes plus ordinaires.)

Exemple trivial, "square [\ s -] * dance" correspondrait directement sur "squaredance" mais un match de proximité sur "square dance" et "square-dance" (puisque '-' est un délimiteur) .J'ai besoin de savoir, sur la base de l'expression rationnelle, de chercher "square" et " danse "séparément, mais à proximité les uns des autres

Je suis un jeu pour la challe nge, mais je préfère utiliser le code établi. Mon instinct me dit que ce sera un crochet interne au moteur regex, mais je ne connais rien de tel. Aucune suggestion?

+0

Les motifs de recherche peuvent-ils être arbitrairement complexes? Si vous prenez le temps de créer un index, pourquoi ne pas décoder votre format de stockage et rechercher les bits qui vous intéressent? –

Répondre

4

Le re pragma peut produire les informations que vous semblez être intéressé par

use strict; 
use warnings; 
use re qw(Debug DUMP); 

my $re = qr/square[\s-]*dance/; 

'Let\'s go to the square dance!' =~ $re; 

Sortie:.

Compiling REx "square[\s-]*dance" 
Final program: 
    1: EXACT <square> (4) 
    4: STAR (17) 
    5: ANYOF[\11\12\14\15 \-][+utf8::IsSpacePerl] (0) 
    17: EXACT <dance> (20) 
    20: END (0) 
anchored "square" at 0 floating "dance" at 6..2147483647 (checking anchored) minlen 11 
Freeing REx: "square[\s-]*dance" 

Malheureusement, il ne semble pas être un crochet programmatique pour obtenir cette information . Vous devez intercepter la sortie sur STDERR et l'analyser. preuve de concept rugueux:

sub build_regexp { 
    my $string = shift; 
    my $dump; 

    # save off STDERR and redirect to scalar 
    open my $stderr, '>&', STDERR or die "Can't dup STDERR"; 
    close STDERR; 
    open STDERR, '>', \$dump or die; 

    # Compile regexp, capturing DUMP output in $dump 
    my $re = do { 
     use re qw(Debug DUMP); 
     qr/$string/; 
    }; 

    # Restore STDERR 
    close STDERR; 
    open STDERR, '>&', $stderr or die "Can't restore STDERR"; 

    # Parse DUMP output 
    my @atoms = grep { /EXACT/ } split("\n", $dump); 

    return $re, @atoms; 
} 

Utilisez cette façon:

my ($re, @atoms) = build_regexp('square[\s-]*dance'); 

$re contient le motif, @atoms contient une liste des parties littérales du motif. Dans ce cas, c'est

1: EXACT <square> (4) 
    17: EXACT <dance> (20) 
+0

Dommage qu'il ait besoin de rediriger STDERR pour obtenir les données, mais c'est une solution spectaculaire. Je vous remercie! – Trueblood

Questions connexes