我正在尝试使用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 :(得分: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设置为空字符串,而不是将其保留为未定义。