2016-04-08 160 views
2

我想動態地創建編譯正則表達式。那麼,沒問題:簡明的編譯方式動態創建正則表達式

my $rx = join('|', keys %replacement_hash); 

我想編譯它以避免重複調用的開銷。沒問題:

$rx = qr/$rx/; 

雖然問題是什麼 - 對於這樣一個微不足道的操作來說太長了。兩行和兩個額外的時間,我需要提及變量名稱,所以如果我決定重命名它,我需要在全部3個位置進行更改。

到目前爲止,我已經跟要麼使用一個輔助功能(這仍然必須有地方來存放該功能的缺點):

sub qr_expr { qr/$_[0]/ } 
# and later 
my $rx = qr_expr(join('|', keys %replacement_hash)); 

或只是清楚地內聯在我需要它相同的功能:

my $rx = sub{qr/$_[0]/}->(join('|', keys %replacement_hash)); 

有沒有辦法更簡潔地寫出來?

+3

你可以使用['map'(http://perldoc.perl.org/functions/map.html):'我( $ rx)= map {qr/$ _ /} join('|',keys%replacement_hash)'。 –

+0

@HunterMcMillen,不錯!如果只有它不需要額外的上下文()arond'my' list ... –

+0

map返回一個列表,如果你只想捕獲第一個元素(在這種情況下只有一個元素),你需要使用括號,否則你會得到列表的大小。 –

回答

3
my ($re) = map qr/$_/, join '|', map quotemeta, @strings; 

你可能不需要編譯它。大多數情況下,您最終會將其嵌入到另一種模式(例如/^$re\z//($re)/)中,強制重新編譯該模式。 (/$re/沒有重新編譯,也沒有等效的=~ $re。)

此外,Perl會緩存它編譯的最後一個模式的編譯形式。如果要求再次編譯相同的模式,它只需返回緩存副本。

在這兩種這些情況,以下就足夠了:

my $pat = join '|', map quotemeta, @strings; 
+0

雖然普通字符串的確與qr //'相當,'/ o'似乎仍然提供5-10%的增加,令我驚訝。我希望很久以前擺脫它。 –