gpt4 book ai didi

regex - 在正则表达式中使用替换比后续替换更快吗?

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

我有一个很简单的问题。在我工作的地方,我看到了很多正则表达式。在Perl中使用它们来替换和/或消除文本中的某些字符串,例如:

$string=~s/^.+\///;
$string=~s/\.shtml//;
$string=~s/^ph//;

我了解您无法连接第一个和最后一个替换,因为您可能只想在执行第一次替换后在字符串的开头替换 ph。但是,我会将第一个和第二个正则表达式与交替在一起: $string=~s/(^.+\/|\.shtml)//;因为我们正在处理成千上万个文件(+500,000个),所以我想知道哪种方法最有效。

最佳答案

您的表情不相等
这个:

$string=~s/^.+\///;
$string=~s/\.shtml//;
替换文本 .shtml以及直到最后一个斜杠(包括最后一个斜杠)的所有内容。
这个:
$string=~s/(^.+\/|\.shtml)//;
替换文本 .shtml或直到最后一个斜杠(包括最后一个斜杠)的所有内容。
这是组合正则表达式的一个问题:与几个简单的正则表达式相比,单个复杂的正则表达式更难编写,更难以理解和调试。
哪个更快可能没关系
即使您的表达式相等,使用一个或另一个表达式也不会对程序的速度产生重大影响。像 s///这样的内存中操作比文件I/O快得多,并且您已表明要执行大量文件I/O。
您应该使用 Devel::NYTProf之类的文件来配置您的应用程序,以查看这些特定的替换是否实际上是瓶颈(我怀疑它们是瓶颈)。不要浪费时间优化已经非常快的功能。
变更阻碍了优化器
请记住,您正在比较苹果和橙子,但是如果您仍然对性能感到好奇,则可以看到perl如何使用 re pragma评估特定的正则表达式:
$ perl -Mre=debug -e'$_ = "foobar"; s/^.+\///; s/\.shtml//;'
...
Guessing start of match in sv for REx "^.+/" against "foobar"
Did not find floating substr "/"...
Match rejected by optimizer
Guessing start of match in sv for REx "\.shtml" against "foobar"
Did not find anchored substr ".shtml"...
Match rejected by optimizer
Freeing REx: "^.+/"
Freeing REx: "\.shtml"
正则表达式引擎具有优化器。优化器搜索必须出现在目标字符串中的子字符串。如果找不到这些子字符串,则匹配将立即失败,而不检查正则表达式的其他部分。
使用 /^.+\//,优化器知道 $string必须包含至少一个斜杠才能匹配;如果找不到任何斜杠,它将立即拒绝该匹配,而无需调用完整的正则表达式引擎。 /\.shtml/发生了类似的优化。
这是perl对组合正则表达式的作用:
$ perl -Mre=debug -e'$_ = "foobar"; s/(?:^.+\/|\.shtml)//;'
...
Matching REx "(?:^.+/|\.shtml)" against "foobar"
0 <> <foobar> | 1:BRANCH(7)
0 <> <foobar> | 2: BOL(3)
0 <> <foobar> | 3: PLUS(5)
REG_ANY can match 6 times out of 2147483647...
failed...
0 <> <foobar> | 7:BRANCH(11)
0 <> <foobar> | 8: EXACT <.shtml>(12)
failed...
BRANCH failed...
1 <f> <oobar> | 1:BRANCH(7)
1 <f> <oobar> | 2: BOL(3)
failed...
1 <f> <oobar> | 7:BRANCH(11)
1 <f> <oobar> | 8: EXACT <.shtml>(12)
failed...
BRANCH failed...
2 <fo> <obar> | 1:BRANCH(7)
2 <fo> <obar> | 2: BOL(3)
failed...
2 <fo> <obar> | 7:BRANCH(11)
2 <fo> <obar> | 8: EXACT <.shtml>(12)
failed...
BRANCH failed...
3 <foo> <bar> | 1:BRANCH(7)
3 <foo> <bar> | 2: BOL(3)
failed...
3 <foo> <bar> | 7:BRANCH(11)
3 <foo> <bar> | 8: EXACT <.shtml>(12)
failed...
BRANCH failed...
4 <foob> <ar> | 1:BRANCH(7)
4 <foob> <ar> | 2: BOL(3)
failed...
4 <foob> <ar> | 7:BRANCH(11)
4 <foob> <ar> | 8: EXACT <.shtml>(12)
failed...
BRANCH failed...
5 <fooba> <r> | 1:BRANCH(7)
5 <fooba> <r> | 2: BOL(3)
failed...
5 <fooba> <r> | 7:BRANCH(11)
5 <fooba> <r> | 8: EXACT <.shtml>(12)
failed...
BRANCH failed...
Match failed
Freeing REx: "(?:^.+/|\.shtml)"
注意输出的时间。由于这种交替,优化器无法启动,并且会执行完整的正则表达式引擎。在最坏的情况下(没有匹配项),将针对字符串中的每个字符测试交替的每个部分。这不是很有效。
所以,轮换比较慢,对吗?没有为什么...
这取决于你的数据
同样,我们正在比较苹果和橙子,但与:
$string = 'a/really_long_string';
合并后的正则表达式实际上可能会更快,因为使用 s/\.shtml//时,优化器必须在拒绝匹配之前扫描大部分字符串,而合并后的正则表达式会快速匹配。
您可以为此乐趣 benchmark,但是由于您要比较不同的事物,因此它实际上是没有意义的。

关于regex - 在正则表达式中使用替换比后续替换更快吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36420517/

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