当前位置:  开发笔记 > 编程语言 > 正文

如何只使用正则表达式匹配有效的罗马数字?

如何解决《如何只使用正则表达式匹配有效的罗马数字?》经验,为你挑选了6个好方法。

考虑到我的另一个问题,我决定甚至不能创建一个匹配罗马数字的正则表达式(更不用说将生成它们的无上下文语法)

问题是只匹配有效的罗马数字.例如,990不是"XM",它是"CMXC"

我为此制作正则表达式的问题是,为了允许或不允许某些字符,我需要回顾一下.例如,让我们花费成千上万.

我可以允许M {0,2} C?M(允许900,1000,1900,2000,2900和3000).但是,如果匹配在CM上,我不能允许跟随字符为C或D(因为我已经在900).

我怎样才能在正则表达式中表达这一点?
如果它在正则表达式中根本无法表达,它是否可以在无上下文语法中表达出来?



1> paxdiablo..:

尝试:

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

打破它:


M{0,4}

这指定了数千个部分,并且基本上将它限制在0和之间4000.这是一个相对简单的:

   0:   matched by M{0}
1000: M        matched by M{1}
2000: MM       matched by M{2}
3000: MMM      matched by M{3}
4000: MMMM     matched by M{4}

(CM|CD|D?C{0,3})

稍微复杂一点,这适用于数百个部分并涵盖了所有可能性:

  0:   matched by D?C{0} (with D not there)
100: C        matched by D?C{1} (with D not there)
200: CC       matched by D?C{2} (with D not there)
300: CCC      matched by D?C{3} (with D not there)
400: CD       matched by CD
500: D        matched by D?C{0} (with D there)
600: DC       matched by D?C{1} (with D there)
700: DCC      matched by D?C{2} (with D there)
800: DCCC     matched by D?C{3} (with D there)
900: CM       matched by CM

(XC|XL|L?X{0,3})

与前一节相同的规则,但对于十位:

 0:   matched by L?X{0} (with L not there)
10: X        matched by L?X{1} (with L not there)
20: XX       matched by L?X{2} (with L not there)
30: XXX      matched by L?X{3} (with L not there)
40: XL       matched by XL
50: L        matched by L?X{0} (with L there)
60: LX       matched by L?X{1} (with L there)
70: LXX      matched by L?X{2} (with L there)
80: LXXX     matched by L?X{3} (with L there)
90: XC       matched by XC

(IX|IV|V?I{0,3})

这是单位部分,处理09并也类似于前两节(罗马数字,尽管他们看似古怪,遵循一些逻辑规则,一旦你搞清楚它们是什么):

0:   matched by V?I{0} (with V not there)
1: I        matched by V?I{1} (with V not there)
2: II       matched by V?I{2} (with V not there)
3: III      matched by V?I{3} (with V not there)
4: IV       matched by IV
5: V        matched by V?I{0} (with V there)
6: VI       matched by V?I{1} (with V there)
7: VII      matched by V?I{2} (with V there)
8: VIII     matched by V?I{3} (with V there)
9: IX       matched by IX


@Aashish:当罗马人成为不可忽视的力量时,"MMMM"是正确的方式.在核心帝国陷入困境之后很长一段时间内,这一问题就出现了.
不应该是M {0,3}吗?
避免匹配空字符串的任何解决方案?
@paxdiablo这是我发现mmmcm失败的原因.String regx ="^ M {0,3}(CM | CD | D?C {0,3})(XC | XL | L?X {0,3})(IX | IV | V?I {0, 3})$"; if(input.matches(regx)) - >这对于java中的MMMCM/MMMM评估为false.

2> James Curran..:

实际上,你的前提是有缺陷的.990 IS "XM",以及"CMXC".

与三年级老师相比,罗马人对"规则"的关注度要低得多.只要它加起来,就可以了.因此,"IIII"和4的"IV"一样好.而"IIM"对998来说非常酷.

(如果你在处理这个问题时遇到了麻烦......记住英语拼写直到1700年才正式化.在此之前,只要读者能够弄明白,它就足够了).


当然,这很酷.但在我看来,我的"严格的三年级老师"语法需要一个更有趣的正则表达式问题......
好的詹姆斯,一个应该是一个严格的作者,但一个宽容的读者.
人性是那么有趣.规则是规则,除非它们不是.

3> Corin..:

为了避免空字符串,你需要重复模式四次替换每个匹配0具有1反过来,并交代V,LD:

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

在这种情况下(因为这个模式使用^$)你最好先检查空行,不要打扰它们.如果你正在使用单词边界,那么你没有问题,因为没有空单词这样的东西.(至少正则表达式没有定义一个;不要开始哲学思考,我在这里务实!)


在我自己特定的(现实世界)案例中,我需要在单词结尾处使用匹配数字,而我找不到其他方法.我需要清除我的纯文本文档中的脚注编号,其中"红海cl和大堡礁cli " 等文本已被转换为the Red Seacl and the Great Barrier Reefcli.但我还是不得不与像有效的单词的问题Tahitifantastic擦洗成Tahitfantasti.



4> smileart..:

只是为了保存它:

(^(?=[MDCLXVI])M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$)

匹配所有罗马数字.不关心空字符串(至少需要一个罗马数字字母).应该在PCRE,Perl,Python和Ruby中工作.

在线Ruby演示:http://rubular.com/r/KLPR1zq3Hj

在线转换:http://www.onlineconversion.com/roman_numerals_advanced.htm


我不知道为什么,但主要答案在MemoQ的自动翻译列表中对我不起作用.但是,此解决方案可以 - 但不包括字符串开始/结束符号.

5> Jonathan Lef..:

幸运的是,数字范围限制在1..3999左右.因此,你可以建立正则表达式.


每个部分都将处理罗马符号的变幻莫测.例如,使用Perl表示法:

 = m/(CM|DC{0,3}|CD|C{1,3})?/;

重复并组装.

补充:可以进一步压缩:

 = m/(C[MD]|D?C{0,3})/;

由于"D?C {0,3}"条款无法匹配,因此不需要问号.并且,很可能,括号应该是非捕获类型 - 在Perl中:

 = m/(?:C[MD]|D?C{0,3})/;

当然,它也应该不区分大小写.

你也可以扩展这个来处理James Curran提到的选项(允许XM或IM用于990或999,CCCC用于400等).

 = m/(?:[IXC][MD]|D?C{0,4})/;



6> Salvador Dal..:
import re
pattern = '^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$'
if re.search(pattern, 'XCCMCI'):
    print 'Valid Roman'
else:
    print 'Not valid Roman'

对于真正想了解逻辑的人,请看一下关于deepintopython的 3页上的逐步说明。

与原始解决方案(具有M{0,4})的唯一区别是,因为我发现'MMMM'不是有效的罗马数字(同样,旧罗马人很可能没有考虑过这么大的数字,因此会与我不同意)。如果您是不同意的古罗马人之一,请原谅我并使用{0,4}版本。

推荐阅读
无名有名我无名_593
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有