2010-05-10 11 views
8

Sto lavorando a un'implementazione abbastanza specializzata motore di ricerca in Perl, cerca (da regex) documenti in modo specifico delimitato (un sottoinsieme di: punct:) stringhe da un file di testo. Sto facendo i soliti trucchi per l'indicizzazione dei motori di ricerca, ma c'è un problema.Come posso identificare i "gettoni" (parola sbagliata) di un'espressione regolare

Alcuni di ricerca modelli regex includono, per necessità, delimitatori utilizzati nel file. "Ok, penso a me stesso," prossimità di parole, quindi ... facile "... e quel lato dell'equazione è abbastanza semplice

Il trucco è che, poiché i modelli di ricerca sono espressioni regolari, non posso facilmente determinate le parole specifiche che dovrei cercare nei dati indicizzati (pensate a "split" se stiamo parlando di stringhe più ordinarie)

Esempio banale, "square [\ s -] * dance" corrisponderebbe direttamente alla "quadratura" ma una corrispondenza di prossimità su "square dance" e "square-dance" (poiché "-" è un delimitatore). Devo sapere, in base alla regex, cercare "square" e " danza "separatamente, ma vicini l'uno all'altro

Sono un gioco per il challe nge, ma preferisco usare il codice stabilito. Il mio istinto mi dice che sarà un gancio interno al motore regex, ma non conosco niente del genere. Eventuali suggerimenti?

+0

Gli schemi di ricerca possono essere arbitrariamente complessi? Se hai bisogno di tempo per creare un indice, perché non decodificare il tuo formato di archiviazione e cercare le parti che ti interessano? –

risposta

4

Il re pragma in grado di produrre le informazioni ti sembra di essere interessato a

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

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

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

uscita:.

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" 

Purtroppo, non sembra essere un gancio programmatico per ottenere queste informazioni . Dovresti intercettare l'output su STDERR e analizzarlo. proof-of-concept di massima:

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; 
} 

usarlo in questo modo:

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

$re contiene il modello, @atoms contiene una lista delle porzioni letterale del modello. In questo caso, è

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

Peccato che sia necessario reindirizzare STDERR per ottenere i dati, ma questa è una soluzione spettacolare. Grazie! – Trueblood

Problemi correlati