Используя Perl, как мне показать контекст вокруг поискового запроса в результатах поиска? - PullRequest
1 голос
/ 05 марта 2009

Я пишу скрипт на Perl, который ищет термин в больших частях текста. То, что я хотел бы отобразить обратно пользователю, - это небольшая часть текста вокруг поискового термина, чтобы пользователь мог иметь контекст использования этого поискового термина. Результаты поиска Google являются хорошим примером того, чего я пытаюсь достичь, когда контекст вашего поискового запроса отображается под заголовком ссылки.

Мой основной поиск использует это:

if ($text =~ /$search/i ) {
    print "${title}:${text}\n";
}

($ title содержит заголовок элемента, в котором был найден поисковый запрос) Это слишком много, потому что иногда $ text будет содержать сотни строк текста.

Это будет отображаться в Интернете, поэтому я мог бы просто предоставить заголовок в виде ссылки на фактический текст, но для пользователя нет контекста.

Я пытался изменить свое регулярное выражение для захвата 4 слов до и 4 слов после поискового запроса, но столкнулся с проблемами, если поисковый запрос был в самом начале или в конце $ text.

Что было бы хорошим способом сделать это? Я попытался выполнить поиск CPAN, потому что уверен, что у кого-то есть модуль для этого, но я не могу придумать правильные условия для поиска. Я бы хотел бы сделать это без модулей, если это возможно, потому что установка модулей здесь - это боль. У кого-нибудь есть идеи?

Ответы [ 4 ]

3 голосов
/ 05 марта 2009

Вы можете использовать $ and $' to get the string before and after the match. Then truncate those values appropriately. But as blixtor points out, shlomif is correct to suggest using @ + and @ - to avoid the performance penalty imposed by $ и # '-

$foo =~ /(match)/;

my $match = $1;
#my $before = $`;
#my $after = $';
my $before = substr($foo, 0, $-[0]);
my $after =  substr($foo, $+[0]);

$after =~ s/((?:(?:\w+)(?:\W+)){4}).*/$1/;
$before = reverse $before;                   # reverse the string to limit backtracking.
$before =~ s/((?:(?:\W+)(?:\w+)){4}).*/$1/;
$before = reverse $before;

print "$before -> $match <- $after\n";
2 голосов
/ 05 марта 2009

Я бы предложил использовать позиционные параметры - @ + и @ - (см. Perldoc perlvar), чтобы найти позицию в строке соответствия и сколько это займет.

2 голосов
/ 05 марта 2009

Ваша первая попытка 4 слова до / после была не слишком далека.

Попытка:

if ($text =~ /((\S+\s+){0,4})($search)((\s+\S+){0,4})/i) {
    my ($pre, $match, $post) = ($1, $3, $4);
    ...
}
0 голосов
/ 05 марта 2009

Вы можете попробовать следующее:

if ($text =~ /(.*)$search(.*)/i ) {

  my @before_words = split ' ', $1;
  my @after_words = split ' ',$2;

  my $before_str = get_last_x_words_from_array(@before_words);
  my $after_str = get_first_x_words_from_array(@after_words); 

  print $before_str . ' ' . $search . ' ' . $after_str;

}

Некоторый код явно опущен, но это должно дать вам представление о подходе.

Что касается извлечения названия ... Я думаю, что этот подход не слишком хорош для этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...