【问题标题】:Regex not capturing matching in expected groups正则表达式未捕获预期组中的匹配
【发布时间】:2017-02-16 00:49:12
【问题描述】:

我一直在处理需求,我需要在以下字符串上创建一个正则表达式:

startDate:[2016-10-12T12:23:23Z:2016-10-12T12:23:23Z]

此字符串可以有多种变体,如下所示:

startDate:[*;2016-10-12T12:23:23Z]
startDate:[2016-10-12T12:23:23Z;*]
startDate:[*;*]
上面表达式中的

startDate 是一个键名,可以是 endDate、updateDate 等任何内容,这意味着我们不能在表达式中对其进行硬编码。虽然[a-zA-Z_0-9]*

可以接受键名作为任何单词

我正在使用以下编译模式

Pattern.compile("([[a-zA-Z_0-9]*):(\\[[[\\*]|[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}[Z]];[[\\*]|[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}[Z]]\\]])");

模式匹配,但创建的组不是我所期望的。我想要下面括号括起来的组:

(startDate):([*:2016-10-12T12:23:23Z])

group1 = "startDate"
group2 = "[*;2016-10-12T12:23:23Z]"

能否请您帮我正确表达 Java 和组?

【问题讨论】:

  • but the groups created are not what I expect. ... 目前有哪些群组?
  • dateMatcher.group(0) = "s" dateMatcher.group(1) = "s" @TimBiegeleisen
  • startDate:[*:*] 你能把这个缩小一点吗?如果您愿意接受冒号两侧的时间戳,甚至检查冒号两侧的时间戳也没有意义。
  • @TimBiegeleisen 我必须提取冒号周围的时间戳,以便稍后进行一些日期范围比较。你建议如何缩小范围?
  • 如果没有出现时间戳,那里还会出现什么?您至少需要半固定结构才能在此处编写健壮的正则表达式。

标签: java regex regex-group


【解决方案1】:

这是一个使用您原来的正则表达式的解决方案,经过修改,它实际上返回了您想要的组:

String content = "startDate:[2016-10-12T12:23:23Z:2016-10-12T12:23:23Z]";
Pattern pattern = Pattern.compile("([a-zA-Z_0-9]*):(\\[(?:\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z|\\*):(?:\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z|\\*)\\])");
Matcher matcher = pattern.matcher(content);
// remember to call find() at least once before trying to access groups
matcher.find();

System.out.println("group1 = " + matcher.group(1));
System.out.println("group2 = " + matcher.group(2));

输出:

group1 = startDate
group2 = [2016-10-12T12:23:23Z:2016-10-12T12:23:23Z]

此代码已在 IntelliJ 上进行了测试,似乎工作正常。

【讨论】:

    【解决方案2】:

    您使用[ 而不是( 来包装选项(即使用|)。

    例如,以下代码适用于我:

    Pattern pattern = Pattern.compile("(\\w+):(\\[(\\*|\\d{4}):\\*\\])");
    Matcher matcher = pattern.matcher(text);
    if (matcher.matches()) {
        for (int i = 0; i < matcher.groupCount() + 1; i++) {
            System.out.println(i + ":" + matcher.group(i));
        }
    } else {
        System.out.println("no match");
    }
    

    为了简化事情,我只使用年份,但我确信它可以与完整的时间戳字符串一起使用。

    此表达式在组中捕获的内容超出您的需要,但您可以使用 (?: ) 构造将它们设为“非捕获”。

    请注意,我使用预定义的字符类简化了一些正则表达式。详情请见http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html

    【讨论】:

    • 感谢@sprinter!这是导致问题的选项周围缺少圆括号:)
    • 关于非捕获组的好提示。我投了一票;-)
    • 这可能有效,但请注意它实际上与原始问题中描述的时间戳不匹配。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多