我想用下面的正則表達式捕捉到幾個文字:如何加快我的Perl正則表達式匹配?
$text_normal = qr{^(\/F\d+) FF (.*?) SCF SF (.*?) MV (\(.*?)SH$};
字符串的樣本是象下面這樣:
my $text = '/F12345 FF FF this is SCF SF really MV (important stuff SH';
可以在被改寫,以加快匹配?
我想用下面的正則表達式捕捉到幾個文字:如何加快我的Perl正則表達式匹配?
$text_normal = qr{^(\/F\d+) FF (.*?) SCF SF (.*?) MV (\(.*?)SH$};
字符串的樣本是象下面這樣:
my $text = '/F12345 FF FF this is SCF SF really MV (important stuff SH';
可以在被改寫,以加快匹配?
這非常依賴於您正在掃描的數據的配置文件。
你可以做的是識別你的RE的一部分,它過濾出最多的輸入,並且 爲該表達做一個單獨的更簡單的RE。
例如,如果只有5%您輸入日期包含'MV'
字符串, 你可以過濾這個第一且僅當 簡單的一個是真的
所以,你將不得不申請全面更復雜的RE:
if ($text_normal =~/MV /) {
$text_normal = qr{^(\/F\d+) FF (.*?) SCF SF (.*?) MV (\(.*?)SH$};
if .......
}
}
如果你只是在第一遍中檢查一個靜態字符串來清除問題,可以考慮基準測試'index('MV')'是否比執行正則表達式匹配更快。 – 2009-10-20 11:09:44
沒有看到一些示例數據很難說。
通常,避免使用.*
是個好主意。尋找任何可能的不必要的回溯源,並消除它們。
你也許可以用切片逃脫一個split
,如果你的需求很簡單。
my @vals = (split//, $string)[0,2,5,7];
優化正則表達式沒有單一的答案。你可以看什麼特定的正則表達式與re編譯做:
use re 'debugcolor';
一旦你看到它遍歷字符串,你看到它是有問題,並從那裏調整你的正則表達式。當你這樣做時,你會學到一些關於正則表達式的引擎。
您也應該檢查出Mastering Regular Expressions,它告訴你的正則表達式是如何工作的,以及爲什麼有些模式是比別人慢。
+1你每天都會學到新的東西! – draegtun 2009-10-20 08:34:34
回溯是殺死正則表現的最可靠的方法之一,但不幸的是,這似乎並不是一種能夠完全消除.
通配符以支持字符類的情況,禁止重新捕獲包含大寫字符。 (如果這個禁令確實存在,你可以取代你的.*?
有,比方說,[a-z ]*
。)您還可以減少使用{}
,設置文字匹配的最小/最大數量的回溯的可能性,如.{0,10}?
如果比賽能不會超過10個字符。
(.*)
意味着您在處理任何重複次數的「SCF SF」之前,您會發現指示它是下一次捕獲的次數,通過使其非貪婪,您仍處理的能力即使是「SCF SF '會在'FF'後出現在捕捉中。我認爲你正在處理很多你不需要的情況。
最好的方式來優化正則表達式有時使得它更神祕 - 但你一定要想辦法使表達較早失敗。 (.*?)
雖然不是「貪婪」,但絕對是也是寬容。
下面是一個更詳細的,但更快的失敗替代你的第二次捕獲。
((?:[^S]|S[^C]|SC[^F]|SCF[^ ]|SCF [^S]|SCF S[^F])*)
但是你可以優化它甚至更多,如果你認爲該字符串應該\bSCF\b
自動進行捕捉,並承諾只希望「\ BSCF SF \ B」。因此,您可以將其重寫爲:
((?:[^S]|S[^C]|SC[^F]SCF\B)*) SCF SF
但是,您可以通過回溯控制來優化這些字符串。如果你認爲世界上沒有任何方法可以讓SCF作爲一個單詞出現,並且SF不會跟隨有效的輸入。要做到這一點,你可以在它周圍增加一個組,括號爲(?>
和)
。
(?>((?:[^S]|S[^C]|SC[^F]SCF\B)*)) SCF SF
這意味着匹配邏輯決不會嘗試重新評估它所捕獲的內容。如果之後的字符不能成爲「SCF SF」,則整個表達式失敗。並且它在嘗試適應「MV」和其他子表達式之前就失敗了。
事實上,給出關於分隔符的唯一某些表達式,該表達式最快的性能將是:
$text_normal = qr{^(\/F\d+) FF (?>((?:[^S]|S[^C]|SC[^F]SCF\B)*))SCF SF (?>((?:[^M]|M[^V]|MV\B)*))MV (?>(\((?:[^S]|S[^H]|SH.)*))SH$};
另外,詳細的,詳盡的否定匹配可以替代由負lookaheads--表達但我不知道如何在性能上起作用。但負面看aheads會的工作是這樣的:
((?:.(?! SCF))*) SCF SF
這意味着,這個捕獲我想,是不是開始字符串「SCF SF」空格的任何字符。
因爲這是'qr {}',所以不需要轉義'/'。 – 2009-10-20 11:20:27
你確定這是你程序的一部分嗎? – Schwern 2009-10-22 23:50:11