【问题标题】:How to capture multiline repeated groups using regular expression如何使用正则表达式捕获多行重复组
【发布时间】:2021-08-06 05:01:13
【问题描述】:

我一直在尝试在 Kotlin 应用程序中编写一个正则表达式,我可以使用它来解析由时间戳前缀分隔的多行日记条目,如下所示:

28-03-2020 23:00:00 - This
is
line
1

28-03-2021 14:23:15 - This
is
line
2


每个重复组应捕获时间戳 (1) 以及在行首文本结尾处的下一个时间戳模式 (2) 之前出现的所有文本。

因此,在上面的示例中,我希望得到以下输出:

第 1 场比赛

第 1 组28-03-2020 23:00:00

第 2 组This\nis\nline\n1\n

第 2 场比赛

第 1 组28-03-2020 14:23:15

第 2 组This\nis\nline\n2\n

到目前为止,我已经设法想出了一个可以捕获第一个匹配项的正则表达式:

^(\d{2}-\d{2}-\d{4} \d{2}:\d{2}:\d{2}) -([\s\S]*?)(?=^\d{2}.*?)

但是,到目前为止,我一直未能成功捕获重复组。有人可以帮忙吗?

我已经设置了这个regex101 session 来测试它。

【问题讨论】:

  • 如果您需要更多帮助,请分享您的 Kotlin 代码:重复分组是什么意思?此外,您的正则表达式至少应该看起来像 ^(\d{2}-\d{2}-\d{4} \d{2}:\d{2}:\d{2}) -([\s\S]*?)(?=^\d{2}|\z)
  • 我已经接受了第四只鸟的回答,因为它给了我完成Kotlin solution所需的一切。

标签: java regex kotlin


【解决方案1】:

如果你想匹配:

每个重复组应捕获时间戳和所有文本 直到下一个时间戳模式开始时才会发生 行或文本的结尾。

您可以捕获组 1 中字符串开头的时间戳。

无需在行首设置换行符或数字等结束边界,使用第 2 组中的负前瞻来捕获所有不以类似时间戳的模式开头的行。

^(\d{2}-\d{2}-\d{4}\h+\d{2}:\d{2}:\d{2})\h+-\h*(.*(?:\R(?!\d{2}-\d{2}-\d{4}\h+\d{2}:\d{2}:\d).*)*)
  • ^ 字符串开始
  • (\d{2}-\d{2}-\d{4}\h+\d{2}:\d{2}:\d{2}) 捕获group 1,匹配日期时间模式
  • \h+-\h* 匹配 - 前面有 1+ 个水平空白字符,后面是可选字符
  • ( 捕获第 2 组
    • .*整行匹配
    • (?:非捕获组
      • \R 匹配换行符
      • (?!\d{2}-\d{2}-\d{4}\h+\d{2}:\d{2}:\d) 负前瞻,直接在右侧断言不是日期时间之类的模式
      • .*如果断言为真,则匹配整行
    • )* 如果换行符不是以类似模式的日期时间开头,则匹配换行符和其余行
  • )关闭第二组

Regex demo | Java demo

例如

String regex = "^(\\d{2}-\\d{2}-\\d{4} \\d{2}:\\d{2}:\\d{2})\\h+-\\h*(.*(?:\\R(?!\\d{2}-\\d{2}-\\d{4} \\d{2}:\\d{2}:\\d).*)*)";
String string = "28-03-2020 23:00:00 - This\n"
+ "is\n"
+ "line\n"
+ "1\n\n"
+ "28-03-2021 14:23:15 - This\n"
+ "is\n"
+ "line\n"
+ "2\n\n\n\n"
+ "28-03-2020 23:00:00 - This\n"
+ "is\n"
+ "12\n"
+ "line\n"
+ "1";

Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
Matcher matcher = pattern.matcher(string);

while (matcher.find()) {
    System.out.println(matcher.group(1));
    System.out.println(matcher.group(2));
    System.out.println("--------------------");
}

输出

28-03-2020 23:00:00
This
is
line
1

--------------------
28-03-2021 14:23:15
This
is
line
2



--------------------
28-03-2020 23:00:00
This
is
12
line
1
--------------------

【讨论】:

    【解决方案2】:

    你应该像这样使用Pattern.DOTALL

    public static void main(String[] args) {
        String s = "28-03-2020 23:00:00 - This\n"
            + "is\n"
            + "line\n"
            + "1\n"
            + "\n"
            + "28-03-2021 14:23:15 - This\n"
            + "is\n"
            + "line\n"
            + "2\n"
            + "\n";
        Pattern pat = Pattern.compile(
            "(\\d{2}-\\d{2}-\\d{4} \\d{2}:\\d{2}:\\d{2})\\s*-\\s*(.*?)\n\n",
            Pattern.DOTALL);
        Matcher m = pat.matcher(s);
        while (m.find()) {
            System.out.println("Group 1 : " + m.group(1));
            System.out.println("Group 2 : " + m.group(2));
        }
    }
    

    输出:

    Group 1 : 28-03-2020 23:00:00
    Group 2 : This
    is
    line
    1
    Group 1 : 28-03-2021 14:23:15
    Group 2 : This
    is
    line
    2
    

    【讨论】:

      【解决方案3】:

      这个怎么样。

      public static void main(String[] args) {
          String s = "28-03-2020 23:00:00 - This\n"
                  + "is\n"
                  + "line\n"
                  + "1\n"
                  + "\n"
                  + "28-03-2021 14:23:15 - This\n"
                  + "is\n"
                  + "line\n"
                  + "2\n"
                  + "\n";
      
          Pattern r = Pattern.compile("^(\\d{2}-\\d{2}-\\d{4} \\d{2}:\\d{2}:\\d{2}) -(?:[\\s\\D]*?)^(\\d{1,2})",Pattern.MULTILINE);
          Matcher matcher = r.matcher(s);
          
          while(matcher.find()) {
              System.out.println("Group 1 : " + matcher.group(1));
              System.out.println("Group 2 : " + matcher.group(2));
          }
      }
      

      输出如下。

      Group 1 : 28-03-2020 23:00:00
      Group 2 : 1
      Group 1 : 28-03-2021 14:23:15
      Group 2 : 2
      

      【讨论】:

        猜你喜欢
        • 2017-09-13
        • 2011-03-11
        • 2017-01-07
        • 2019-12-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-30
        相关资源
        最近更新 更多