2009-08-05 50 views
1

我想分析其可能包含混合的模式,比如正則表達式匹配的時間跨度

1-4pm 
1pm-5pm 
noon to 11pm 
noon to midnight 
etc. 

我想提取開始和結束時間的數據。我如何通過正則表達式來實現這一點。我知道我無法支持所有可能的輸入格式,但我怎樣才能實現最大限度的支持?


這是我的表達 ^(([AZ] +)?)\ S *([0-9] {1,2} [:] [0-9] {0 ((?[az] +)?| 2} \ s * [am | pm | am | pm] [。])?\ s * [ - | to | \ |/| =] \ s (?[0-9] {1,2} [:]?[0-9] {0,2} \ s * [am | pm | am | pm] [。]))?$

它涵蓋了幾乎所有的組合。我只想知道在這個正則表達式中是否有任何優化。 在這裏,dayPart將消耗所有開始的非數字字符來處理TimeSpan是以中午,午夜等開始,還是像週日我們可以忽略的任何值。 startTime會嘗試以任何格式消耗任何時間,如果它在那裏。 endPart和EndTime也一樣。

回答

2

首先,定義匹配單個時間點的模式。給出你的例子,它可能是這樣的:

(noon|midnight|[0-9]+\s?(am|pm)?) 

接下來,定義分隔符。也許:

(to|\-) 

最後,結合兩個第一個和第二個之一。假設你的語言支持變量,像:

set timePattern {(noon|midnight|[0-9]+\s?(am|pm)?)} 
set separator {(to|\-)} 
set fullPattern "$timePattern(\s*$separator\s*$timePattern)?" 

一旦你通過通過發動機,你應該能夠得到在匹配表達的部分。你可能需要讓一些組不被捕獲,但我會把它作爲讀者的練習。然後,您可能需要解析各個部分以確定時間。例如,將「1pm」解析爲1和「pm」,並基於此計算時間。

一旦你把它分解成它可以更容易擺弄組成部分,並使表達式更容易理解。儘管如此,在支持帶註釋的多行表達式的某些語言中也可以完成同樣的事情。

+0

你不應該逃避分隔符表達式中的破折號,這是不必要的。 +1的方法。 – Tomalak 2009-08-05 13:27:46

+0

嚴格來說,這是沒有必要的。這是我習慣了的習慣,因爲你必須在一個範圍內特別對待「 - 」。我傾向於在任何地方自動保護它。 2009-08-05 13:41:44

0

沒有太多的事情要做,看起來你可以根據"-""to"進行拆分。

^(.+) ?(-|to) ?(.+)$ 

這將捕獲第一組中的開始時間和第三組中的結束時間。如果你想要一個更具體的語法,你必須指定你打算使用哪種正則表達式。

+0

貪婪的「+」有點問題。我認爲最好把第一個paren改成'(。+?)'。但我認爲這是你所說的「你必須指定哪種變體的正則表達式」。 ;-) – Tomalak 2009-08-05 13:31:36

1

根據不同的語言,您可以'建立'匹配模式。 紅寶石,例如,將允許你這樣做:

time_spec = /noon|midnight|\d{1,2}/ 
sep = /-|to/ 
match = /#{time_spec}\s*#{sep}\s*#{time_spec}/ 

但是,因爲這看起來像是因爲它得到推廣,這將是複雜得多,爲什麼不建立某種形式的解析器(使用Flex/yacc?),它會比正則表達式保持得更好? 當你開始支持一系列的輸入,如1pm/1p/13:00/13正則表達式開始創建更多的問題,然後解決方案。