Bra*_*roy 6 regex perl alternation
我有一个很直截了当的问题.在我工作的地方,我看到很多正则表达式都来了.它们在Perl中用于替换和/或删除文本中的一些字符串,例如:
$string=~s/^.+\///;
$string=~s/\.shtml//;
$string=~s/^ph//;
Run Code Online (Sandbox Code Playgroud)
我知道你不能连接第一个和最后一个替换,因为你可能只想ph在第一次替换后在字符串的开头替换.但是,我会将第一个和第二个正则表达式放在一起进行交替:$string=~s/(^.+\/|\.shtml)//;因为我们正在处理数千个文件(+500,000),所以我想知道哪种方法最有效.
Thi*_*Not 10
这个:
$string=~s/^.+\///;
$string=~s/\.shtml//;
Run Code Online (Sandbox Code Playgroud)
替换文本.shtml 和所有内容,包括最后一个斜杠.
这个:
$string=~s/(^.+\/|\.shtml)//;
Run Code Online (Sandbox Code Playgroud)
取代或者文本.shtml 或一切直到并包括最后的斜线.
这是组合正则表达式的一个问题:单个复杂正则表达式比几个简单的正则表达式更难编写,更难理解,更难调试.
即使你的表达式是等效的,使用其中一个可能不会对你的程序速度产生重大影响.像内存中的操作s///明显快于文件I/O,并且你已经表明你正在进行大量的文件I/O.
您应该使用Devel :: NYTProf之类的内容来分析您的应用程序,看看这些特定的替换是否实际上是一个瓶颈(我怀疑它们是否存在).不要浪费时间优化已经很快的事情.
请记住,您正在比较苹果和橙子,但如果您仍然对性能感到好奇,可以看看perl如何使用repragma评估特定的正则表达式:
$ 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"
Run Code Online (Sandbox Code Playgroud)
正则表达式引擎有一个优化器.优化器搜索必须出现在目标字符串中的子字符串; 如果找不到这些子字符串,则匹配会立即失败,而不会检查正则表达式的其他部分.
有了/^.+\//,优化器知道$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)"
Run Code Online (Sandbox Code Playgroud)
注意输出多长时间.由于交替,优化器不会启动并执行完整的正则表达式引擎.在最坏的情况下(没有匹配),交替的每个部分都针对字符串中的每个字符进行测试.这不是很有效.
所以,轮换更慢,对吧?没有为什么...
我们再次比较苹果和橘子,但是:
$string = 'a/really_long_string';
Run Code Online (Sandbox Code Playgroud)
组合的正则表达式实际上可能更快,因为s/\.shtml//优化器必须在拒绝匹配之前扫描大部分字符串,而组合的正则表达式快速匹配.
你可以对此进行基准测试以获得乐趣,但由于你在比较不同的东西,它基本上没有意义.