2008-11-15 89 views
1

比方說,我有這樣的如何讓這個正則表達式更緊湊?

Small 0.0..20.0 0.00 1.49 25.71 41.05 12.31 0.00 80.56 

我想要捕獲的最後6位數字,並忽略和前兩組數字的一行文字。

對於這個練習,讓我們忽略這樣一個事實,即只做一些字符串拆分而不是正則表達式可能更容易。

我有這樣的正則表達式的作品,但那種可怕的期待

^(Small).*?[0-9.]+.*?[0-9.]+.*?([0-9.]+).*?([0-9.]+).*?([0-9.]+).*?([0-9.]+).*?([0-9.]+).*?([0-9.]+) 

是否有某種方式來壓縮呢?

例如,是否可以將對最後6個數字的檢查合併爲單個語句,該語句仍將結果存儲爲6個單獨的組匹配?

+0

「少笨拙」 - 雙重否定 - 不好英語。 「更有勇氣」 - 不好英語。該死。 – 2008-11-15 22:29:16

+0

好點。謝謝:) – 2008-11-15 22:59:36

+0

如果程序員遇到問題,他可能會想:「我會用正則表達式!」現在程序員有兩個問題...對於個人的教育,你能告訴我們爲什麼一個字符串split/tokenizer不適合這個特殊的問題嗎?奇怪的例外是有趣的瞭解。 – 2008-11-15 23:14:11

回答

3

這裏是最短的,我可以得到:

^Small\s+(?:[\d.]+\s+){2}([\d.]+)\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)\s*$ 

,因爲每個捕獲必須明確指定它必須是長。雖然沒有必要捕捉「小」。但是,如果可以的話,最好是具體的(而不是),並且在兩端定位。

5

如果你想保持每一個單獨的反向引用,你別無選擇,只能「拼出來」 - 如果你使用重複,你可以捕獲所有六個「一體」或只有最後一個,取決於您放置圓括號的位置。所以不,不可能壓縮正則表達式,仍然保留所有六個單獨的匹配。

一個稍微更有效的(雖然沒有華麗的)正則表達式是:

^Small\s+[0-9.]+\s+[0-9.]+\s+([0-9.]+)\s+([0-9.]+)\s+([0-9.]+)\s+([0-9.]+)\s+([0-9.]+)\s+([0-9.]+) 

,因爲它的空間明確匹配。你的正則表達式會導致很多回溯。我正則表達式在28步,你匹配106

正如旁白:在Python中,你可以簡單地做一個

>>> pieces = "Small 0.0..20.0 0.00 1.49 25.71 41.05 12.31 0.00 80.56".split()[-6:] 
>>> print pieces 
['1.49', '25.71', '41.05', '12.31', '0.00', '80.56'] 
1

可用性,你應該使用字符串替換從複合材料部件構建正則表達式。

$d = "[0-9.]+"; 
$s = ".*?"; 

$re = "^(Small)$s$d$s$d$s($d)$s($d)$s($d)$s($d)$s($d)$s($d)"; 

至少可以看到過去的模式的結構,改變一個部分改變它們。

如果你想獲得真正ANSI你可以做一個簡短的使用元語法,並使其更容易閱讀:

$re = "^(Small)_#D_#D_(#D)_(#D)_(#D)_(#D)_(#D)_(#D)"; 
$re = str_replace('#D','[0-9.]+',$re); 
$re = str_replace('_', '.*?' , $re); 

(這樣,它也可以輕鬆地將改變什麼空間令牌的定義是,還是什麼一個數字令牌)