gpt4 book ai didi

regex - perl6 正则表达式子规则和命名正则表达式比显式正则表达式慢得多;如何使它们同样快?

转载 作者:行者123 更新时间:2023-12-04 04:14:35 25 4
gpt4 key购买 nike

我有一个包含 1608240 行的数据文件。该文件是分段的。每个部分在开始行都有一个唯一的单词,所有部分在该部分的最后一行都有相同的单词“doneSection”。

我正在尝试通过执行以下操作来找出某些部分(代码由 original post 中的@raiph 重新格式化,以使代码更易于解释):

# using named subrules/regex is EXTREMELY slow;
# it reads about 2 lines per second, and grinds to halt
# after about 500 lines: (>> is the right word boundary)
perl6 -e 'my regex a { [ <{<iron copper carbon>.join("||")}> ] };
my $x = 0;
for "/tmp/DataRaw".IO.lines {
$*ERR.print( "$x 1608240 \r" );
++$x;
.say if m/:i beginSection \s+ <a> >>/ or
(m/:i \s+ <a> \s+ /
ff
m/:i doneSection/);
}'

# however, if I explicitly write out the regex instead of using a subrule,
# it reads about 1000 lines per second, and it gets the job done:
perl6 -e 'my $x = 0;
for "/tmp/DataRaw".IO.lines {
$*ERR.print( "$x 1608240 \r" );
++$x;
.say if m/:i beginSection \s+
[ iron || copper || carbon ] >>/ or
(m/:i \s+
[ iron || copper || carbon ] \s+ /
ff
m/:i doneSection/);
}'

我的问题是,如何使子规则与显式正则表达式一样快,或者至少不停止?我更喜欢使用更高级别的抽象。这是正则表达式引擎内存问题吗?我也尝试过使用:
my $a=rx/ [ <{ < iron copper carbon > .join("||") }> ] /

它同样慢。

我无法发布我的数据文件的 160 万行,但您可能可以生成一个类似的文件用于测试目的。

感谢您的任何提示。

最佳答案

问题不在于使用子规则/命名正则表达式。这是正则表达式中的内容。它的:

[ <{<iron copper carbon>.join("||")}> ]
对比
[ iron || copper || carbon ]
以下应消除速度差异。请尝试并评论您的结果:
my regex a { || < iron copper carbon > }
注意 < iron copper ... 中的前导空格而不是 <iron copper ...> .后者表示称为 iron 的子规则。带有参数 copper等等。前者意味着“引号”列表文字只是 as it does in the main language (尽管在主要语言中前导空格是可选的).1
匹配器列表可以放在数组变量中:
my @matchers = < iron copper carbon >;
my regex a { || @matchers }
@matchers 中的匹配器可以是任意正则表达式,而不仅仅是字符串:
my @matchers = / i..n /, / cop+er /, / carbon /;
my regex a { || @matchers }
警告:以上工作,但在写这个答案时,我遇到了,现在已经解决了 @ symbol'd array interpolation doesn't backtrack 的问题。 .

how to make subrule as fast as explicit regex


这不是关于它是明确的。大约是 regex interpolation这涉及运行时评估。
通常,P6 正则表达式是用它们自己的正则表达式语言编写的,默认情况下在编译时编译。
但是 P6 正则表达式语言包括注入(inject)代码的能力,然后在运行时进行评估(只要它不危险)。2
这可能很有用,但会产生运行时开销,有时可能很重要。
(也有可能你有一些糟糕的 Big O与你使用运行时评估相关的算法性能。如果是这样,它甚至比运行时插值更糟糕,因为它是一个大O问题。我'我没有费心去分析它,因为最好按照我上面的代码使用完全编译的正则表达式。)

I have also tried using:

my $a=rx/ [ <{ < iron copper carbon > .join("||") }> ] /
这仍然不能避免运行时插值。这个构造:
<{ ...  }>
通过在运行时评估大括号内的代码然后将其注入(inject)外部正则表达式来进行插值。
脚注
1 P6“语言”实际上是 DSLs的交织集合.
2 除非你明确写了 use MONKEY-SEE-NO-EVAL; (或只是 use MONKEY; ) pragma为了对注入(inject)攻击负责,包含注入(inject)字符串的正则表达式的插值在编译时受到限制,以确保不可能进行注入(inject)攻击,如果是,P6 将拒绝运行代码。您编写的代码不会受到攻击,因此编译器可以让您按照自己的方式编写代码,并毫不费力地编译代码。

关于regex - perl6 正则表达式子规则和命名正则表达式比显式正则表达式慢得多;如何使它们同样快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54604854/

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