使用正则表达式匹配多个或零个出现次数(按此顺序)

3

我希望使用Groovy正则表达式来匹配罗马数字(我没有在Java中尝试过,但应该是相同的)。 我在这个网站上找到了一个答案,其中有人建议使用以下正则表达式:

/M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})/

问题在于在Groovy中,像/V?I{0,3}/这样的表达式不是贪婪的。所以对于字符串"Book number VII",匹配器/V?I{0,3}/返回的是"V",而不是期望的"VII"。
显然,如果我们使用模式/VI+/,那么我们会得到匹配"VII"...但是如果字符串是"Book number V",这种解决方案就无效了,因为我们将得不到任何匹配...
我试图通过使用贪婪量词/VI{0,3}+/或者/VI*+/来强制捕获最大字符,但我仍然得到了"V"而不是"VII"的匹配。
有什么想法吗?

1
在Java中它肯定是贪婪的(对“VIII”运行,在第3组中得到“VIII”,而不是“V”。同时,仅测试正则表达式“V?I {0,3}”也会产生贪婪的结果)。您确定您正在Groovy中观察到此行为吗?似乎很奇怪Groovy将使用不同的正则表达式引擎。 - Mark Peters
啥?所以,?是贪婪模式,但是{n,m}不是? - Bart Kiers
不完全是关于主题的,但正则表达式似乎过度指定了。它将通过无效的罗马数字,因此不能用于错误检查。但显然很麻烦。那么像 [MCDXLIV]+ 这样的东西怎么样? - Tony Ennis
我刚在Java中运行了这个代码,结果是正确的。所以Java返回贪婪匹配的结果。但是Groovy不会。我正在使用Groovy控制台运行一个脚本,版本是groovy 1.7.0,并且{0,3}不是贪婪匹配。奇怪的是,{n,m}是贪婪匹配,但只有当n!=0时。同样地,.*只有在与0个字符匹配不符合模式时才是贪婪匹配。 - Alex
2个回答

0
为什么不直接使用 (IX|IV|V?I{1,3}|V)? 这样更简单明了。

谢谢。这个可以工作,因为V?I{1,3}比只有V的优先级更高。我很困惑,因为V?I{0,3}本应该可以单独工作(在Java中可以,但在Groovy中不行)。 - Alex
那么...选择这个回答作为“最佳答案”怎么样? - Chochos

0
我找到了我的错误所在。 问题是像/V?I{0,3}//V?I*/这样的模式甚至可以匹配空字符串...因此对于像"Book VII"这样的字符串,匹配器将抛出以下结果匹配:
Result[0] --> ''
Result[1] --> '' 
Result[2] --> ''
Result[3] --> '' 
Result[4] --> '' 
Result[5] --> 'VII'
Result[6] --> '' 

贪婪匹配的结果已经出现了(Result[5])。 我的问题在于我总是选择第一个匹配项(Result[0]),而这只有在模式未被空字符串匹配时才有效。
例如,建议使用的模式/V?I{1,3}|V/只会抛出一个结果,因此选择第一个匹配结果是可以的:
Result[0] --> 'VII'

这是因为空字符串不符合模式。

希望这能帮助其他人。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接