短语搜索文本文件

时间:2012-10-25 12:20:15

标签: perl search text phrases

给出一个短语,例如“我正在搜索文本”和一个包含单词列表的文本文件。

我必须找到文本文件中是否存在单词的每个组合。

例如,我必须搜索“我”,“我是”,“我正在搜索”,“我正在搜索”,“搜索”等事件。

我更喜欢用perl编写这个,我需要一个运行得更快的最佳解决方案。

示例文本文件:

I \n
am searching \n
Text \n
searching for \n 
searching for a \n
for searching       ---> my program should not match this 
etc

2 个答案:

答案 0 :(得分:1)

下面的代码打印了您要匹配的所有子词。

$phrase = 'I am searching for a text';
$\ = "\n";

@words = ();
print "Indices:";
while( $phrase =~ /\b\w+\b/g ) {
    push @words, {word => $&, begin => $-[0], end => $+[0]};
}

$num_words = $#words + 1;
print 'there are ', $num_words, ' words';


for( $i=0; $i<$num_words; $i++ ) {
    for( $j=$i; $j<$num_words; $j++ ) {
        ($start,$finish) = ($words[$i]->{begin}, $words[$j]->{end});
        $sub_phrase = substr $phrase, $start, $finish-$start;
        print "$i-$j: $sub_phrase";
    }
}

一些解释:

  1. $ \只是为了打印&#39;更容易
  2. $ phrase - 使用您的示例
  3. @words是对记录的引用数组
  4. 每条记录都是一个散列,其中包含单词本身,索引指向开头,索引指向单词的结尾
  5. 我是一个正则表达式,我正在迭代。我正在寻找一个单词边界,一个或多个单词字符和一个单词边界。
  6. $ +和$ - 是最后一个RE的匹配索引的特殊变量
  7. $&安培;是最后一次RE匹配的特殊变量
  8. 然后我有一个嵌套循环:$ i,外部循环变量是第一个单词。 $ j是硬道理。这涵盖了所有组合。
  9. 我从第一个单词的开头到最后一个单词的结尾计算$ sub_phrase。
  10. 要完成练习,您需要将所有sub_phrase保存到一个数组中(而不是&#39; print&#39; do&#39; push&#39; into @permutations)。然后迭代你的文本文件,对于每一行,尝试匹配每个排列。

答案 1 :(得分:1)

您可以构造一个适用于所有这些情况的表达式。下面,我将展示如何在Perl中构建构建(尽管您可以将产品用于您的目的)。

use List::Util qw<reduce>;

our ( $a, $b );

my $regex       
    = "\n^\n( "
    . join( "\n| "
    , @{( reduce { 
            my $r = ref( $a ) ? $a : [ "$a " ];
            my $s = $r->[0];
            [ "$b (?> [ ] $s)?", @$r ] 
        } 
        reverse split ' ', 'I am searching for a text'
        )}
    )
    . "\n)\n\\s*\n\$"
    ;
say join( "\n# ", split "\n", $regex );

# ^
# ( I (?> [ ] am (?> [ ] searching (?> [ ] for (?> [ ] a (?> [ ] text )?)?)?)?)?
# | am (?> [ ] searching (?> [ ] for (?> [ ] a (?> [ ] text )?)?)?)?
# | searching (?> [ ] for (?> [ ] a (?> [ ] text )?)?)?
# | for (?> [ ] a (?> [ ] text )?)?
# | a (?> [ ] text )?
# | text 
# )
# \s*
# $

map { say foreach m/$regex/xo } <DATA>;
  • 我添加了锚点,因为你指出它应该匹配整行。
  • 完成的正则表达式中有空格,但它使用/x来忽略它们。这就是我们用[ ]指定空间的原因。
  • 分组符号(?>...)是非捕获(?:...)的变体,但失败的速度要快很多。请参阅http://perldoc.perl.org/perlre.html#(%3f%3epattern)
  • 请参阅List::Util::reduce