java - 用于检测持续时间的正则表达式

标签 java regex

我为持续时间写了一个正则表达式

正则表达式是

([0-9]+ (?:[y|Y]ears?|[y|Y]rs?|[m|M]o?nths?|[d|D]a?ys?) ?)+

您可以在 this regex tool 上查看.

匹配的测试用例

  1. 今年 10 月,我将完成 24 岁。现在我3 个月 短意味着 23 岁 9 个月 19 天
  2. ATL 正在为过去10 年 23 个月 19 天的研究工作提供服务。

应该匹配但不匹配的测试用例

  1. 二十三岁
  2. 22 年 12 个月 30 天前发生了一场灾难。

疑惑

  1. 帮我检测数字的英文单词,看第3和第4种情况。

已编辑 1

我添加了 reFourDigits 变量来处理 1220 类型的案例。但它没有捕获这一点。请帮助我。以下是有关上述问题的所有详细信息。

public static final String reDigit = "(?:[O|o]ne|[t|T]wo|[t|T]hree|[f|F]our|[f|F]ive|[s|S]ix|[s|S]even|[e|E]ight|[n|N]ine)";
    public static final String reTeen = "(?:[t|T]wenty|[t|T]hirty|[f|F]orty|[f|F]ifty|[s|S]ixty|[s|S]eventy|[e|E]ighty|[n|N]inety)";
    public static final String re10_19 = "(?:[t|T]en|[e|E]leven|[t|T]welve|[t|T]hirteen|[f|F]ourteen|[f|F]ifteen|[s|S]ixteen|[s|S]eventeen|[e|E]ighteen|[n|N]ineteen)";
    public static final String reTwoDigits = "(?:(?:" + reTeen + "[- ])?" + reDigit + "|" +  re10_19  + "|" + reTeen + ")";
    public static final String reThreeDigits = "(?:(?:" + reDigit + " hundred (?:and)?)?" + reTwoDigits + "|" + reDigit + " hundred)";
    public static final String reFourDigits = "(?:" + reTwoDigits + " hundred (?:and)? " + reTwoDigits + ")"; 
    public static final String reSixDigits = "(?:(?:" + reThreeDigits + " thousand (?:and )?)?" + reThreeDigits + "|" + reThreeDigits + " thousand|" + reFourDigits + ")";
    public static final String reTwelveDigits = "(?:(?:" + reSixDigits + " million (?:and )?)?" + reSixDigits + "|" + reSixDigits + " million)";

模式是

String patternString = "\\b( ?(?:[,0-9]+|"+Constants.reTwelveDigits+") ?)\\b";

当我运行 There are two22 apples 时。它找到两个字符串 twentytwenty2,而不是 twenty22

最佳答案

就个人而言,我会推荐一个真正的解析器。正则表达式是可能的,但它可能会变成一个非常冗长的模式。下面我用了define来自正则表达式的 PHP 方言,以避免重复模式。如果您选择的正则表达式引擎没有这样的结构,那么您可能需要扩展每个定义,这会导致一个相当长的模式。您仍然可以通过使用简单的字符串连接动态构建模式字符串来避免必须自己写出来。

(?(DEFINE)(?<Digit>one|two|three|four|five|six|seven|eight|nine))
(?(DEFINE)(?<Teen>twenty|thirty|forty|fifty|sixty|seventy|eighty|ninety))
(?(DEFINE)(?<TwoDigits>((?&Teen)-)?(?&Digit)|ten|eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen|(?&Teen)))
(?(DEFINE)(?<ThreeDigits>((?&Digit) hundred (and )?)?(?&TwoDigits)|(?&Digit) hundred))
(?(DEFINE)(?<SixDigits>((?&ThreeDigits) thousand (and )?)?(?&ThreeDigits)|(?&ThreeDigits) thousand))
(?(DEFINE)(?<TwelveDigits>((?&SixDigits) million (and )?)?(?&SixDigits)|(?&SixDigits) million))

fiddle :http://regex101.com/r/oM4oF2

将定义添加到您的表达式中,
然后你可以用 (?:[0-9]+|(?&TwelveDigits)) 替换每个 [0-9]+

编辑: 据我所知,Java 没有可重用的子模式,因此您必须完全扩展该模式。

string reDigit = "(?:one|two|three|four|five|six|seven|eight|nine)";
string reTeen = "(?:twenty|thirty|forty|fifty|sixty|seventy|eighty|ninety)";
string reTwoDigits = "(?:(?:" + reTeen + "-)?" + reDigit + "|ten|eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen|" + reTeen + ")";
string reThreeDigits = "(?:(?:" + reDigit + " hundred (?:and )?)?" + reTwoDigits + "|" + reDigit + " hundred)";
string reSixDigits = "(?:(?:" + reThreeDigits + " thousand (?:and )?)?" + reThreeDigits + "|" + reThreeDigits + " thousand)";
string reTwelveDigits = "(?:(?:" + reSixDigits + " million (?:and )?)?" + reSixDigits + "|" + reSixDigits + " million)";

string reNumeric = "\\b(?:[0-9]+|" + reTwelveDigits + ")\\b";

我找不到 Java fiddle 站点,所以我改用 JavaScript,它有一个类似的正则表达式引擎:http://jsfiddle.net/f6RmN/

关于java - 用于检测持续时间的正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24263847/

相关文章:

java - 当 Activity 被销毁然后重新创建时,未调用观察者并且后值无法从后台线程工作

java - 我将如何在另一个类中调用以下方法? java

java - 需要一些帮助才能从引号和括号中获取数据

java - 如何从字符串中提取日期并将其放入Java中的日期变量

regex - R:在某个字符后大写所有内容

java - dbunit 测试用例抛出 NoSuchTableException

java - Jenkins:EMMA 验证错误

java - 检查错误输出位于我的错误列表中

Jquery — 将 URL 正则表达式插入大写句子?

regex - 如何在 SMLNJ 中使用正则表达式