使用Perl,如何在搜索结果中显示搜索词周围的上下文?

时间:2009-03-05 18:41:04

标签: perl search full-text-search

我正在编写一个Perl脚本,它在大部分文本中搜索一个术语。我想要显示给用户的是搜索词周围的一小部分文本,因此用户可以获得使用此搜索词的位置的上下文。 Google搜索结果就是我想要完成的一个很好的例子,搜索字词的上下文会显示在链接标题下。

我的基本搜索是使用它:

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

($ title包含找到搜索词的项目的标题) 但这太过分了,因为有时候$ text会持有数百行文字。

这将显示在网络上,所以我可以提供标题作为实际文本的链接,但没有用户的上下文。

我尝试修改我的正则表达式以捕获之前的4个单词和搜索词后的4个单词,但如果搜索词位于$ text的开头或结尾,则会遇到问题。

实现这一目标的好方法是什么?我尝试搜索CPAN,因为我确定有人有这个模块,但我想不出正确的搜索条件。如果可能的话,我会喜欢在没有模块的情况下这样做,因为在这里安装模块是一件痛苦的事。有没有人有任何想法?

4 个答案:

答案 0 :(得分:3)

您可以使用$ 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";

答案 1 :(得分:2)

您之前/之后的4个单词的初始尝试并不太远。

尝试:

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

答案 2 :(得分:2)

我建议使用位置参数 - @ +和@ - (参见perldoc perlvar)来查找匹配字符串中的位置以及需要多少。

答案 3 :(得分:0)

您可以尝试以下方法:

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;

}

显然省略了一些代码,但这应该让您了解该方法。

至于提取标题......我认为这种方法不适合这种方式。