\s*
(甚至\s\s*
)替换为\s+
会显著提升此输入的速度?use Benchmark qw(:all);
$x=(" " x 100000) . "_\n";
$count = 100;
timethese($count, {
'/\s\s*\n/' => sub { $x =~ /\s\s*\n/ },
'/\s+\n/' => sub { $x =~ /\s+\n/ },
});
我注意到在我的代码中,一个慢速的正则表达式s/\s*\n\s*/\n/g
- 当给定一个450KB的输入文件,其中有大量的空格和一些非空格字符,以及最后一个换行符时,该正则表达式会挂起并永远无法完成。
我本能地用 s/\s+\n/\n/g; s/\n\s+/\n/g;
替换了正则表达式并且一切都好了。
但为什么它会快那么多呢?经过使用 re Debug => "EXECUTE"
我注意到 \s+
版本被优化为只运行一次: http://pastebin.com/0Ug6xPiQ
Matching REx "\s*\n" against " _%n"
Matching stclass ANYOF{i}[\x09\x0a\x0c\x0d ][{non-utf8-latin1-all}{unicode_all}] against " _%n" (9 bytes)
0 <> < _%n> | 1:STAR(3)
SPACE can match 7 times out of 2147483647...
failed...
1 < > < _%n> | 1:STAR(3)
SPACE can match 6 times out of 2147483647...
failed...
2 < > < _%n> | 1:STAR(3)
SPACE can match 5 times out of 2147483647...
failed...
3 < > < _%n> | 1:STAR(3)
SPACE can match 4 times out of 2147483647...
failed...
4 < > < _%n> | 1:STAR(3)
SPACE can match 3 times out of 2147483647...
failed...
5 < > < _%n> | 1:STAR(3)
SPACE can match 2 times out of 2147483647...
failed...
6 < > < _%n> | 1:STAR(3)
SPACE can match 1 times out of 2147483647...
failed...
8 < _> <%n> | 1:STAR(3)
SPACE can match 1 times out of 2147483647...
8 < _> <%n> | 3: EXACT <\n>(5)
9 < _%n> <> | 5: END(0)
Match successful!
Matching REx "\s+\n" against " _%n"
Matching stclass SPACE against " _" (8 bytes)
0 <> < _%n> | 1:PLUS(3)
SPACE can match 7 times out of 2147483647...
failed...
我知道如果没有换行符,Perl 5.10+将立即使正则表达式失败(而不运行它)。我怀疑它是使用换行符的位置来减少搜索量。对于上述所有情况,它似乎巧妙地减少了涉及回溯的工作量(通常/\s*\n/
与一串空格的字符串相对,需要指数时间)。有人能解释为什么\s+
版本如此更快吗?
另外请注意,\s*?
并不会提供任何加速。
\s
匹配\n
也不太有用。一个不是换行符的空白字符是[^\S\n]
,或者你可以使用 "horizontal whitespace"\h
。 - Borodin/\s*\n/
和/\s+\n/
查看实时演示。请注意,只有在字符串不匹配的情况下才会更快。如果匹配成功,则需要相同的时间。 - Thomas Ayoub\s\s*
应该与\s+
相同,而你发布的两个正则表达式是不同的。然而,我同意即使在你发布的这两个正则表达式之间的性能差异也令人惊讶! - rjh[^\S\n]*\n
也很慢... - rjh