perl - 在 perl 中替换文本中的一组单词的速度 -
问题描述
上下文优先:我试图在维基百科页面中突出显示歌曲标题。首先,我从页面中获取引用的部分,检查它们是否存在于歌曲标题数据库中,然后突出显示我找到的那些。数据库部分速度惊人,提取歌曲标题(引用它们)也是如此。
因此(我认为)我需要替换 HTML 中的一组单词(标题)并将它们包装在这样的跨度中(对于每个单词):
s/word/<span class="something">word<\/span>/gi
文本长约 100k,列表约 300 个单词(均未预先确定),因此一次替换一个单词的迭代过程太慢(如果可能,我需要将其保持在 < 1 秒)。
所以我已经完成了
my $re = join '|', map { quotemeta($_) } @words;
$dom =~ s/($re)/<span class="something">$1<\/span>/gi;
这似乎有效并且速度很快(在我的基准案例中为 0.64)。
现在我想替换\"$word\"
而不是只是$word
这样我尝试了这个:
my $re = join '|', map { quotemeta(join '', '"', $_, '"') } @words;
速度下降了 10 倍。将速度与 NYTProf 进行比较,所有差异似乎都在内部CORE:substcont
这是为什么?
(非常感谢有关如何避免替换标签内的文本的建议,例如id="word_to_be_replaced"
)
解决方案
我不知道您实际上在做什么,因为您只提出了您认为问题所在的内容(而我们看不到其余的内容)。
首先,你有join '', '"', $_, '"'
,但这只是qq("$_")
。
接下来,如果你有一个被引号包围的单词,你不需要在每个单词周围加上引号。将单词更改分组并在其周围加上引号:
s/ " (?: word1 | word2 | ... ) " /.../x;
我的第一个怀疑是,无论您的模式做什么,都涉及更多的回溯。
为了避免替换 HTML 中可能存在的相同文本,我会使用 HTML 解析器并且只查看文本。但是,这将比已经发生的事情花费更长的时间。
推荐阅读
- nix - Nix:如何用全局覆盖覆盖 stdenv.cc?
- javascript - Javascript document.write函数中是否有引号“和'的替代品
- angular - 在每一步使用 ngFor 的迭代根据索引
- reactjs - 受保护的路由在 API 响应到达之前重定向
- javascript - 如何在 vscode 扩展中打开本地(扩展包内)文件
- angular - Angular,我什么时候可以在 Angular 指令中使用模板引用变量?
- c# - 如何将 CSV 读入列表中的特定对象(包括整数、字符串、性别枚举和 DOB)
- jenkins - 如何在实例 EC2 中命名 Jenkins 从属
- python - 移位结果解释
- ios - 将 NSPersistentCloudKitContainer 迁移到 AppGroup 会导致 CloudKit 重新同步并创建重复对象