2012-02-27 37 views
0

我想解析使用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])?。我认为这将匹配第二小时数(如果有的话),然后.*匹配其余的线,但事实并非如此。相反,最后的.*与第二个小时以及之后的所有内容相匹配。

为什么?的使用不符合第二小时,如果它在那里。这是一个贪婪的问题,还是我以其他方式犯了一个错误?

+0

一个Perl正则表达式不必匹配整个字符串,所以你不需要。* $在最后。 – 2012-02-27 17:34:02

+0

而不是只有一个空的空间,我建议把\ s。它更清晰。 – 2012-02-28 02:56:09

回答

1

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

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

1

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

你可以改变它是这样的:

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

注意,可选部分是现在(.*?([0-9]))?,即第一.*?是搭配一强制性[0-9]。这意味着.*?只有在有第二个数字才能使用时才会使用。

1

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

为了解决这个问题,改变.*?匹配只是非数字字符,这样

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

此外,更改([0-9])?([0-9]*)将设置$ 4至一个空字符串,如果没有第二小时图,而不是让它不确定。

相关问题