我有一个像这样的数组
my @stopWords = ("and","this",....)
我的文字在这个变量中
my $wholeText = "....and so this is...."
我希望在标量wholeText中匹配我的stopWords数组的每个元素的每一个匹配项,并用空格替换它。
这样做的一种方法如下:
foreach my $stopW (@stopWords)
{
$wholeText =~ s/$stopW/ /;
}
这可以工作并替换所有停用词的每次出现。我只是想知道,如果有更短的方法。
像这样:
$wholeText =~ s/@stopWords/ /;
以上似乎并不奏效。
答案 0 :(得分:7)
虽然各种基于map
/ for
的解决方案正常工作,但它们也会针对每个停用词分别对字符串进行正则表达式处理。虽然在给出的示例中这没什么大不了的,但随着目标文本和禁用词列表的增长,它可能会导致严重的性能问题。
Jonathan Leffler和Robert P在正确的轨道上提出了将所有停用词混合成一个正则表达式的建议,但是将所有停用词简单地join
转换为单一的替换是一种粗略的方法,并再次如果禁用词列表很长,则效率低下。
输入Regexp::Assemble,这将为您构建一个更“智能”的正则表达式,以便同时处理所有匹配项 - 我已经使用它来实现最佳效果,最多可以检查1700个左右的单词:
#!/usr/bin/env perl
use strict;
use warnings;
use 5.010;
use Regexp::Assemble;
my @stopwords = qw( and the this that a an in to );
my $whole_text = <<EOT;
Fourscore and seven years ago our fathers brought forth
on this continent a new nation, conceived in liberty, and
dedicated to the proposition that all men are created equal.
EOT
my $ra = Regexp::Assemble->new(anchor_word_begin => 1, anchor_word_end => 1);
$ra->add(@stopwords);
say $ra->as_string;
say '---';
my $re = $ra->re;
$whole_text =~ s/$re//g;
say $whole_text;
哪个输出:
\b(?:t(?:h(?:at|is|e)|o)|a(?:nd?)?|in)\b
---
Fourscore seven years ago our fathers brought forth
on continent new nation, conceived liberty,
dedicated proposition all men are created equal.
答案 1 :(得分:6)
我最好的解决方案:
$wholeText =~ s/$_//g for @stopWords;
您可能希望使用一些\b
和空格来锐化正则表达式。
答案 2 :(得分:3)
怎么样:
my $qrstring = '\b(' . (join '|', @stopWords) . ')\b';
my $qr = qr/$qrstring/;
$wholeText =~ s/$qr/ /g;
连接所有单词以形成'\b(and|the|it|...)\b
';连接周围的括号是必要的,以给它一个列表上下文;如果没有它们,你最终会计算出单词的数量)。 '\b
'元字符标记单词边界,因此可以防止您将'千'变为'thous'。将其转换为带引号的正则表达式;将其全局应用于您的主题字符串(以便在单个操作中删除所有出现的所有停用词)。
您也可以不使用变量“$qr
”:
my $qrstring = '\b(' . (join '|', @stopWords) . ')\b';
$wholeText =~ s/$qrstring/ /g;
我认为我不想维护那些没有变量“$qrstring
”的人的代码;它可能已经完成,但我不认为它会非常易读。
答案 3 :(得分:3)
我的偏执狂版本:
$wholeText =~ s/\b\Q$_\E\b/ /gi for @stopWords;
使用\b
匹配字边界,\Q..\E
以防止任何停用词包含可能被正则表达式引擎解释为“特殊”的字符。
答案 4 :(得分:3)
您可以考虑使用正则表达式连接来创建单个正则表达式。
my $regex_str = join '|', map { quotemeta } @stopwords;
$string =~ /$regex_str/ /g;
请注意,quotemeta
部分只是确保正确转义任何正则表达式字符。
答案 5 :(得分:-1)
grep{$wholeText =~ s/\b$_\b/ /g}@stopWords;