为什么不是?在正则表达式工作?

时间:2012-02-27 05:24:08

标签: regex perl

我正在尝试使用perl解析出现在课程目录中的数据,但我正在努力让我的正则表达式正常工作。

以下是一些数据样本:

Course description goes here; There might be more text; 3 hours of lecture, 2 hours of laboratory. Prerequisite: None
Another course description is here; 3 hours of lecture and laboratory. Prerequisite: None
More description; 4 hours of laboratory. Prerequisite: None

我想捕捉完整的描述(最终分号前的所有内容),然后是小时(后来我将处理与讲座或实验室匹配的小时)。我试图使用的正则表达式是:

/^(.*)\; *([0-9]).*?(lecture|laboratory).*?([0-9])?.*$/

它似乎一直工作到([0-9])?。我认为这将匹配第二个小时数(如果有的话),然后.*之后它将与该行的其余部分匹配,但事实并非如此。相反,最终.*匹配第二个小时以及之后的所有内容。

为什么?的使用与第二小时不匹配(如果有)。这是贪婪的问题,还是我以其他方式犯了错误?

3 个答案:

答案 0 :(得分:1)

由于[0-9]之前的正则表达式非贪婪,因此它将匹配尽可能短的字符串。

最好通过指定要包含的内容来限制匹配,例如使用[^;0-9]*而不是.*?来匹配不应包含分号或数字的序列。

答案 1 :(得分:1)

它与第二个小时不匹配,因为.*?非贪婪:必须采取最短匹配。由于(lecture|laboratory)之后的所有内容都是可选的,因此最短的匹配是.*?不匹配,([0-9])?也不匹配,.*匹配所有内容。

您可以将其更改为:

/^(.*)\; *([0-9]).*?(lecture|laboratory)(.*?([0-9]))?.*$/

请注意,可选部分现在为(.*?([0-9]))?,即第一个.*?必需 [0-9]配对。这意味着.*?仅在有第二个数字时使用。

答案 2 :(得分:1)

问题是第二个.*?总是匹配空字符串。由于?强制匹配尽可能少的字符,并且可选的([0-9])?允许它匹配任何字符。

要解决此问题,请更改.*?以仅匹配非数字字符,例如

/^(.*)\; ([0-9]).*?(lecture|laboratory)[^0-9]*([0-9]*)/

此外,如果没有第二个小时数,则将([0-9])?更改为([0-9]*)会将$ 4设置为空字符串,而不是将其保留为未定义。