我正在编写一个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