2009-08-05 51 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正则表达式开始创建更多的问题,然后解决方案。