[英]Can Perl substitution operator match an element in an array?
我有這樣的數組
my @stopWords = ("and","this",....)
我的文字在這個變量中
my $wholeText = "....and so this is...."
我想匹配標量wholeText中我的stopWords數組的每個元素的每一個出現,並用空格替換它。
一種方法如下:
foreach my $stopW (@stopWords)
{
$wholeText =~ s/$stopW/ /;
}
這適用於並替換所有停用詞的每次出現。 我只是想知道,如果有更短的方法。
像這樣:
$wholeText =~ s/@stopWords/ /;
以上似乎不起作用。
雖然各種基於map
/ for
的解決方案都可以使用 ,但它們也會針對每個停用詞分別對字符串進行正則表達式處理。 雖然在給出的示例中這沒什么大不了的,但隨着目標文本和禁用詞列表的增長,它可能會導致嚴重的性能問題。
喬納森萊弗勒和羅伯特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.
我最好的解決方案
$wholeText =~ s/$_//g for @stopWords;
您可能希望使用一些\\b
和空格來銳化正則表達式。
關於什么:
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
'的人的代碼; 它可能已經完成,但我不認為它會非常易讀。
我的偏執版:
$wholeText =~ s/\b\Q$_\E\b/ /gi for @stopWords;
使用\\b
來匹配單詞邊界,並使用\\Q..\\E
以防萬一你的任何一個停用詞包含可能被正則表達式引擎解釋為“特殊”的字符。
您可以考慮使用正則表達式連接來創建單個正則表達式。
my $regex_str = join '|', map { quotemeta } @stopwords;
$string =~ /$regex_str/ /g;
請注意, quotemeta
部分只是確保正確轉義任何正則表達式字符。
grep{$wholeText =~ s/\b$_\b/ /g}@stopWords;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.