如何编写一个从字符串末尾删除罗马数字的正则表达式?

时间:2019-07-19 23:39:45

标签: regex

我有一个名字列表:

Joe
Bob
Carl
Seth Smith II
Doug IV

我正在尝试编写一个正则表达式,该表达式将返回名称,但不返回罗马数字。所以我的结果集应该像这样:

Joe
Bob
Carl
Seth Smith
Doug

我一直在看消极的展望,但是对此还很陌生,所以我不确定自己是否走对了。谢谢!

1 个答案:

答案 0 :(得分:1)

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

Demo

此正则表达式应该起作用,但是对于您的用例来说可能有点过头了,因为它会按照现代的严格符号检查所有可能的罗马数字,包括成千上万个非常大的数字。它会正确处理符合罗马数字语法的大写字母名称或姓氏,除非它们出现在最后(例如“ Jet LI”),在这种情况下,它们将被处理为罗马数字。

这是我的逻辑:

  1. 让我们匹配字符串的开头,然后匹配一个或多个<any character not followed by space + roman numeral + end>实例以及可能的一个或多个非空格字符(姓氏的最后一个字母,后跟 后跟空格+罗马数字+结束)。
    ^(?:<any non-linebreak character not followed by space + Roman numeral + end>)+\S?
  2. <any non-linebreak character not followed by space + Roman numeral + end>使用此正则表达式进行匹配:
    .(?! <Roman numeral>$)
  3. 用现代严格符号表示的<Roman numeral>可以这样匹配:     
    (?=[MDCLXVI])(M*)(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})
  4. 现在,将所有内容替换在一起以获得最终的正则表达式。

注意:

如果您只想考虑某个范围内的罗马数字,请相应地更新<Roman numeral>部分。例如。小于20的数字将变为(?=[XVI])X?(I[XV]|V?I{0,3})。整个正则表达式将是:

^(?:.(?! (?=[XVI])X?(I[XV]|V?I{0,3})$))+\S?

参考:

Roman Numerals




更新:

这是另一种可能的正则表达式,它应该比上面的正则表达式快,因为它会贪婪地匹配所有非空格,并且仅在出现空格的情况下才检查否定的超前查找。

^(?:\S+| (?!(?=[IVXLCDM])(M*)(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$))+

Demo

这里的一般逻辑是:

^(?:\S+| (?!<Roman numeral>$))+