你的表达不等价
这个:
$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//
时,优化器必须在拒绝匹配之前扫描大部分字符串,而组合的正则表达式匹配得很快。
您可以对此进行基准测试以获取乐趣,但这基本上没有意义,因为您正在比较不同的事物。