Как я могу определить «токены» (неправильное слово) регулярного выражения - PullRequest
8 голосов
/ 10 мая 2010

Я работаю над довольно специализированной реализацией поисковой системы в Perl, она ищет (по регулярному выражению) документы по определенным разделителям (подмножеству: punct :) строк из текстового файла. Я делаю обычные трюки с индексацией в поисковых системах, но есть проблема.

Некоторые шаблоны регулярных выражений поиска по необходимости включают разделители, используемые в файле. «Хорошо, я думаю про себя:« близость слова, потом ... легко »... и эта сторона уравнения достаточно прямолинейна.

Хитрость в том, что поскольку шаблоны поиска являются регулярными выражениями, я не легко определил конкретные слова, которые мне нужно искать в индексированных данных (подумайте «разделить», если мы говорим о более обычных строках).

Тривиальный пример: «квадрат [\ s -] * танец» будет напрямую соответствовать «квадрату», но близкое совпадение для «квадратного танца» и «квадратного танца» (так как «-» является разделителем). Мне нужно знать, основываясь на регулярном выражении, чтобы искать «квадрат» и «танец» отдельно, но рядом друг с другом.

Я играю за вызов, но я бы предпочел использовать установленный код. Моя интуиция говорит мне, что это будет внутренняя привязка к движку регулярных выражений, но я не знаю ничего подобного. Есть предложения?

1 Ответ

4 голосов
/ 11 мая 2010

Прагма re может дать информацию, которая вас интересует.

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

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

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

Выход:

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"

К сожалению, для получения этой информации, похоже, нет программного хука. Вы должны были бы перехватить вывод на STDERR и проанализировать его. Грубое подтверждение концепции:

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

Используйте это так:

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

$re содержит шаблон, @atoms содержит списки буквенных частей шаблона. В данном случае это

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