【问题标题】:Using regex to select 3 groups from a string使用正则表达式从字符串中选择 3 个组
【发布时间】:2022-11-18 00:35:38
【问题描述】:
String s = #Section250342,Main,First/HS/12345/Jack/M,200010 10.00 200011 -2.00,
#Section250322,Main,First/HS/12345/Aaron/N,200010 17.00,
#Section250399,Main,First/HS/12345/Jimmy/N,200010 12.00,
#Section251234,Main,First/HS/12345/Jack/M,200011 11.00

无论在 3 字符串中有单词 /Jack/M 的什么地方,我都想每次使用正则表达式提取与其关联的节号(250342、251234)、日期(200010、200011)和值(10.00、11.00、-2.00) . Sometines 一行可以包含一个或两个值,这样正则表达式就有点混乱了。所以在一天结束时,我们将要提取 3 个差异组。

我试过了

#Section(\d+)(?:(?!#Section\d).)*\bJack/M,(\d+)\h+(\d+(?:\.\d+)?)\s(\d+)\h+([-+]?\d+(?:\.\d+)?)\b

在这里看到它的实际效果 - https://regex101.com/r/JaKeGg/1,它带来了 5 个组而不是 3 个,当这里只有一个值时它似乎不匹配所以我需要帮助。

【问题讨论】:

  • 您是否考虑过使用替代品?像这样:regex101.com/r/6Votk8/1 并只是连接或仅使用您想要的 $1?可能会成功。
  • 如果你有这个字符串 200010 10.00 200011 你不能在一个组中得到 200010 和 200011
  • @sniperd 问题是 #Section251234,Main,First/HS/12345/Jack/M,200011 11.00 这条线没有被正则表达式识别,尽管它应该被正则表达式识别,因为它没有 $4 和 $5 替换
  • 如果我可以使用过滤器@Thefourthbird 做到这一点,是否有可能

标签: java regex string


【解决方案1】:

我认为仅使用正则表达式很难完成你想要的。根据另一个 SO question 的说法,您不能在正则表达式中为同一捕获组设置多个匹配项。相反,实际上只会捕获最后一个匹配模式。

我的建议是在 java 中逐行拆分您的字符串,遍历这些行,检查一行是否包含您搜索“Jack/M”的子字符串,然后使用正则表达式通过搜索更简单的正则表达式模式而不是试图将一个长正则表达式与整个字符串匹配。

关于如何在字符串中查找正则表达式匹配项的详细介绍:https://www.tutorialspoint.com/getting-the-list-of-all-the-matches-java-regular-expressions

【讨论】:

    【解决方案2】:

    您可能会使用一个模式来获取 2 个捕获组,然后在处理捕获 2 个值之后将应该组合在一起的数字组合起来。

    由于示例字符串中的日期和值似乎成对出现,因此您可以将第 2 组值从正则表达式中拆分为一个空格,并使用模运算符创建 2 组以对偶数/奇数事件进行分组。

    #Section(d+)(?:(?!#Sectiond).)*Jack/M,(d+h+[-+]?d+(?:.d+)?(?:s+d+h+[-+]?d+(?:.d+)?)*)
    

    Regex demo | Java demo

    String regex = "#Section(\d+)\b(?:(?!#Section\d).)*\bJack/M,(\d+\h+[-+]?\d+(?:\.\d+)?(?:\s+\d+\h+[-+]?\d+(?:\.\d+)?)*)";
    String string = "#Section250342,Main,First/HS/12345/Jack/M,200010 10.00 200011 -2.00,
    "
            + "#Section250322,Main,First/HS/12345/Aaron/N,200010 17.00,
    "
            + "#Section250399,Main,First/HS/12345/Jimmy/N,200010 12.00,
    "
            + "#Section251234,Main,First/HS/12345/Jack/M,200011 11.00";
    
    Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
    Matcher matcher = pattern.matcher(string);
    
    
    while (matcher.find()) {
        List<String> group2 = new ArrayList<>();
        List<String> group3 = new ArrayList<>();
    
        System.out.println("Group 1: " + matcher.group(1));
        String[] parts = matcher.group(2).split("\s+");
        for (int i = 0; i < parts.length; i++) {
            if (i % 2 == 0) {
                group2.add(parts[i]);
            } else {
                group3.add(parts[i]);
            }
        }
        System.out.println("Group 2: " + Arrays.toString(group2.toArray()));
        System.out.println("Group 3: " + Arrays.toString(group3.toArray()));
    }
    

    }

    输出

    Group 1: 250342
    Group 2: [200010, 200011]
    Group 3: [10.00, -2.00]
    Group 1: 251234
    Group 2: [200011]
    Group 3: [11.00]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-16
      • 2015-01-09
      • 1970-01-01
      • 2018-09-19
      • 2019-06-16
      • 1970-01-01
      • 2018-07-22
      相关资源
      最近更新 更多