Как с помощью Perl показать контекст поискового запроса в результатах поиска?

StackOverflow https://stackoverflow.com/questions/616041

  •  03-07-2019
  •  | 
  •  

Вопрос

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

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

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

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

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

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

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

Это было полезно?

Решение

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

Пытаться:

if ($text =~ /((\S+\s+){0,4})($search)((\s+\S+){0,4})/i) {
    my ($pre, $match, $post) = ($1, $3, $4);
    ...
}

Другие советы

Вы можете использовать $ и $ ', чтобы получить строку до и после совпадения. Затем соответствующим образом обрежьте эти значения. Но, как указывает blixtor, shlomif правильно предложить использовать @ + и @ - , чтобы избежать снижения производительности, налагаемого $ и # '-

$foo =~ /(match)/;

my $match = $1;
#my $before = 

Вы можете использовать $ и $ ', чтобы получить строку до и после совпадения. Затем соответствующим образом обрежьте эти значения. Но, как указывает blixtor, shlomif правильно предложить использовать @ + и @ - , чтобы избежать снижения производительности, налагаемого $ и # '-

; #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";

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

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

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;

}

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top