爲什麼替換\s*
(或甚至\s\s*
)與\s+
導致此輸入的這種加速?爲什麼` s +`在這個Perl正則表達式中比` 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]',或者可以使用「水平空格」'\ h'。 – Borodin
您可以將比較縮小到'/ \ s * \ n /'和'/ \ s + \ n /'[見live](http://rextester.com/DSXF83795)。並且請注意,如果字符串不匹配,它只會更快。在比賽的情況下,它似乎需要同時 –
@ThomasAyoub我不認爲這是縮小比較。 '\ s \ s *'應該與'\ s +'相同,而你發佈的兩個是不同的正則表達式。不過,我同意,即使在你發佈的兩個人之間的表現差異也令人驚訝! – rjh