gpt4 book ai didi

正则表达式和 o 运算符 perl v5.10.1

转载 作者:行者123 更新时间:2023-12-01 09:38:30 25 4
gpt4 key购买 nike

我正在尝试优化一个脚本,该脚本将在特定目录树中的每个文件上运行正则表达式。的所有组件都在正常工作,但我正试图让正则表达式尽可能快地运行。

脚本在每个文件上运行许多正则表达式。我们正在尝试做这样的事情:

我们从一个 YAML 文件开始:

---
-
description: has foo
regex: foo
-
description: has bar
regex: bar
-
description: has foofoo
regex: foofoo
-
description: has barbar
regex: barbar

然后我们将文件读入数组(并通过 qr//运行正则表达式字符串来编译它们),如下所示:

my @regex = @{LoadFile('yaml_file')};
foreach ( @regex ) { $_->{'regex'} = qr/$_->{'regex'}/ }

然后像这样评估每个文件上的每个正则表达式

foreach my $r ( @regex ) {
if ( $slurped_file_text =~ /$r->{'regex'}/ ){
stuff;
}
}

我们发现上述方法比像这样扩展 if/elsif 语句要慢得多:

if( $slurped_file_text =~ /foo/ ){
stuff;
}elsif( $slurped_file_text =~ /bar/ ){
stuff;
}elsif( $slurped_file_text =~ /foofoo/ ){
stuff;
}elsif( $slurped_file_text =~ /barbar/ ){
stuff;
}

但是,这个 if/elsif 方法不是 DRY,我们需要能够轻松地将正则表达式添加到我们的列表中,而不必每次都编辑脚本代码。

在查看 NYTProf of foreach 做事方式后,它表明调用 main::CORE::regcomp 花费了大量时间。

在阅读了类似的问题之后,我们发现了 o 运算符,它应该表示正则表达式自编译以来没有改变,因此不需要重新编译。所以我们尝试了这个(基本上只是将 o 添加到顶部代码):

foreach my $r ( @regex ) {
if ( $slurped_file_text =~ /$r->{'regex'}/o ){
stuff;
}
}

这给了我们想要的速度,但它没有正确评估正则表达式。当存在匹配模式时,它不会返回 true。

我知道 o 运算符不再被大量使用,但是,如上所述,我们仍在使用 perl v5.10.1 并且该版本的文档表明我们需要 o 运算符来获得我们正在寻找的性能为。

我的问题是:

  • 我们怎样才能让使用 o 运算符的正则表达式正确求值?或者您对 o 运算符有什么了解可以解释这里发生的事情吗?
  • 您有没有发现任何更有效的方法来对一组文件运行动态正则表达式列表。

非常感谢任何帮助。

最佳答案

循环版本比展开循环的版本慢的原因是因为总是检查循环版本中的每个正则表达式,但你只检查直到在展开版本中找到匹配项。

my @regexs = map $_->{regex}, @{ LoadFile('yaml_file') };

for my $text (@texts) {
for my $regex (@regexs) {
if ($text =~ $regex) {
stuff;
last; <---- Missing
}
}
}

但由于您似乎并不关心匹配的模式,因此您应该只构建一个模式并编译它。

my $pattern = join '|', map "(?:$_->{regex})", @{ LoadFile('yaml_file') };
my $regex = qr/$pattern/;

for my $text (@texts) {
if ($text =~ $regex) {
stuff;
}
}

关于正则表达式和 o 运算符 perl v5.10.1,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19968618/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com