匹配罗马数字

4

我有一个正则表达式

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

我用它来检测文本中是否存在罗马数字。

eregi("( IX|IV|V?I{0,3}[\.]| M{1,4}[\.]| CM|CD|D?C{1,3}[\.]| XC|XL|L?X{1,3}[\.])", $title, $regs)

但是罗马数字的格式始终是这样的:“IV。”...我已经在eregi示例中添加了数字前的空格和数字后的“。”,但我仍然得到相同的结果。如果文本是像“somethinvianyyhing”这样的东西,则结果将是vi(在两者之间)...
我做错了什么?
1个回答

2

VI之前没有空格,该空格始终属于先前的备选项而不是所有备选项。对于\.也是如此,它始终属于写有它的备选项。

试一下

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

您可以在 Regexr 的这里查看。

这将匹配:

I.
II.
III.
IV.
V.
VI.
VII.
VIII.
IX.
X.

但不匹配:

XI. MMI. MMXI.
somethinvianyyhing

您的罗马数字匹配方法还远没有正确,更准确的方法是这样的:对于50(L)以下的数字

^(?:XL|L|L?(?:IX|X{1,3}|X{0,3}(?:IX|IV|V|V?I{1,3})))$

在Regexr上查看

我只对表面进行了测试,但你可以看出这将变得非常复杂,而且C、D和M在此表达式中仍然缺失。

更不用说特殊情况,例如4=IV=IIII等等。

维基百科关于罗马数字的文章


同样在SO上:https://dev59.com/LnVC5IYBdhLWcg3whRgw - kapa
2
有一个Perl模块可以正确处理罗马数字。要确定您是否拥有此模块,首先要匹配/\b([ivxldcm]+)\b/i,然后检查Roman::isroman($1)是否返回true。否则,您将得到错误的答案。它仅适用于ASCII,这意味着它只能达到4000。最长的合法字符串是MMMDCCCLXXXVIII。使用Unicode,您可以使用更大的罗马数字,例如10,000的ↂ和上划线表示基字符的1000倍。我有一个处理所有这些的模块,但当然它是用Perl编写的。☺ - tchrist

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