【问题标题】:Java/Groovy regex parse Key-Value pairs without delimitersJava/Groovy 正则表达式解析没有分隔符的键值对
【发布时间】:2021-01-04 03:25:56
【问题描述】:

我无法使用正则表达式获取键值对

到目前为止的代码:

String raw = '''
MA1

D. Mueller Gießer

MA2 Peter

Mustermann 2. Mann


MA3 Ulrike Mastorius Schmelzer

MA4 Heiner Becker
s 3.Mann

MA5 Rudolf Peters

Gießer

'''

Map map = [:]

ArrayList<String> split = raw.findAll("(MA\\d)+(.*)"){ full, name, value ->  map[name] = value }


println map

输出是: [MA1:,MA2:彼得,MA3:Ulrike Mastorius Schmelzer,MA4:海纳贝克,MA5:鲁道夫彼得斯]

就我而言,关键是: MA1、MA2、MA3、MA\d(所以 MA 有任意 1 位数字)

在下一个键出现之前,该值绝对是所有内容(包括换行符、制表符、空格等...)

有人知道怎么做吗?

提前致谢, 塞巴斯蒂安

【问题讨论】:

    标签: java regex groovy regex-greedy


    【解决方案1】:

    您可以在第二组中捕获 key 之后的所有内容以及不以 key 开头的所有行

    ^(MA\d+)(.*(?:\R(?!MA\d).*)*)
    

    模式匹配

    • ^ 字符串开始
    • (MA\d+) 捕获 组 1 匹配 MA 和 1+ 位
    • ( 捕获第 2 组
      • .* 匹配该行的其余部分
      • (?:\R(?!MA\d).*)* 匹配所有不以 MA 后跟数字开头的行,其中 \R 匹配任何 unicode 换行符序列
    • )关闭第二组

    Regex demo

    在带有双转义反斜杠的 Java 中

    final String regex = "^(MA\\d+)(.*(?:\\R(?!MA\\d).*)*)";
    

    【讨论】:

    • 谢谢!我刚刚发现此正则表达式存在问题的另一种情况:如果 Key 没有在新行中开始,它不会将其识别为另一个匹配项。
    • @blickfangQ2 我明白了,我错过了那个案子。那你的意思是这样吗? regex101.com/r/eA9I5b/1
    • 第二个链接显示问题,是的。我在一个 excel 文件中有数百个这样的文件,而且变化很大。有的把 MA2 写在一个单独的行,有的做一个制表符,有的只加 20 个空格。该文本字段的不一致是巨大的。所以我的想法。在下一个 Key 出现之前,请绝对拿走所有东西。如果没有其他钥匙,就全部拿走,直到最后。
    • 刚刚认识到您实际上通过第二个链接解决了它!我逃脱了 java 的特殊字符,它似乎工作,太棒了! :) final String regex = "(?s)\\b(MA\\d+)(.*?)(?=MA\\d|\$)"
    【解决方案2】:

    使用

    (?ms)^(MA\d+)(.*?)(?=\nMA\d|\z)
    

    proof

    说明

                             EXPLANATION
    --------------------------------------------------------------------------------
      (?ms)                    set flags for this block (with ^ and $
                               matching start and end of line) (with .
                               matching \n) (case-sensitive) (matching
                               whitespace and # normally)
    --------------------------------------------------------------------------------
      ^                        the beginning of a "line"
    --------------------------------------------------------------------------------
      (                        group and capture to \1:
    --------------------------------------------------------------------------------
        MA                       'MA'
    --------------------------------------------------------------------------------
        \d+                      digits (0-9) (1 or more times (matching
                                 the most amount possible))
    --------------------------------------------------------------------------------
      )                        end of \1
    --------------------------------------------------------------------------------
      (                        group and capture to \2:
    --------------------------------------------------------------------------------
        .*?                      any character (0 or more times (matching
                                 the least amount possible))
    --------------------------------------------------------------------------------
      )                        end of \2
    --------------------------------------------------------------------------------
      (?=                      look ahead to see if there is:
    --------------------------------------------------------------------------------
        \n                       '\n' (newline)
    --------------------------------------------------------------------------------
        MA                       'MA'
    --------------------------------------------------------------------------------
        \d                       digits (0-9)
    --------------------------------------------------------------------------------
       |                        OR
    --------------------------------------------------------------------------------
        \z                       the end of the string
    --------------------------------------------------------------------------------
      )                        end of look-ahead
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-03
      • 1970-01-01
      相关资源
      最近更新 更多