2010-11-11 48 views
2

我正在瀏覽通過John Gruber用Perl編寫的MarkDown代碼,還有一個叫做_Detab的子表將標籤轉換爲空格,同時保留文本的縮進。 Markdown.pl中的代碼行是1314:MarkDown源中的正則表達式與否定類

$text =~ s{(.*?)\t}{$1.(' ' x ($g_tab_width - length($1) % $g_tab_width))}ge; 

這不會導致不必要的回溯?下面的模式不會更有效率嗎?

/([^\t\n]*)\t/ 

或者我錯過了什麼?謝謝。

順便說一句,我只是否定\n而不是\r,因爲所有換行標準預先標準化爲\n

+0

這是我第一次理解perl的一行!沒有'$ _'或'@ _'或任何東西! – Kobi 2010-11-11 19:33:34

+0

@Kobi。哈哈,當我第一次開始編程時,我的學習路徑是HTML - > JavaScript - > Perl。但是我十年來沒有碰過Perl。 – jordanbtucker 2010-11-11 19:49:43

+4

@Kobi:如果你看到'$ _'(順便提一句,它的名字是「* it *」),那麼你可能看的不是很好的Perl代碼。 *它*在* *看起來最少的時候效果最好,在*默認自然風格的小塊中,比如'for(@list} {s/foo/bar/g}' – tchrist 2010-11-11 20:08:35

回答

5

不要想,當你可以基準:

use Benchmark 'cmpthese'; 

my $source = "\t\thello\n\t\t\tworld\n" x 100; 
my $g_tab_width = 8; 

my ($textU, $textN); 

cmpthese(-3, { 
    ungreedy => sub { 
    $textU = $source; 
    $textU =~ s{(.*?)\t}{$1.(' ' x ($g_tab_width - length($1) % $g_tab_width))}ge; 
    }, 

negated => sub { 
    $textN = $source; 
    $textN =~ s{([^\n\t]*)\t}{$1.(' ' x ($g_tab_width - length($1) % $g_tab_width))}ge; 
    }, 
}); 

die "whoops" unless $textN eq $textU; # ensure they do the same thing 

我發現,非貪婪版本(因爲它出現在降價源)比你建議否定字符類快約40%:

  Rate negated ungreedy 
negated 1204/s  --  -30% 
ungreedy 1718/s  43%  -- 

我的猜測是,匹配.比否定的字符類,它彌補了額外的回溯更有效。需要更多的測試來證實這一點。

1

你是對的。這會造成不必要的回溯。是的,你的模式會更有效率。

大多數人並沒有真正理解或思考正則表達式如何工作和/或只是按照他們教過的方式做事。我不知道這段代碼或作者的細節,但是這是一個非常常見的正則表達式,你會在perl代碼中看到。

而且,說實話,對於大多數使用情況來說,它並沒有真正發揮多大的作用。

+2

它可能會導致更多的回溯,但它仍然比替代更有效。請參閱我的答案中的基準測試結果。 – cjm 2010-11-12 08:30:54