【问题标题】:Regex/Java match fields with missing second quote缺少第二个引号的正则表达式/Java 匹配字段
【发布时间】:2018-01-16 14:57:19
【问题描述】:

我在加载到数据库的几个文本文件中有一个以竖线分隔的记录。事实证明,有时一个字段会以引号开头,但不会以引号结尾,这会导致加载失败。这是一个示例记录

||field2|"field3"|"field4|"field5"|||

请注意,字段 4 缺少尾随引号。我想预处理文件并删除这些字段的前导引号,但我似乎无法想出一个有效的正则表达式

我尝试过前瞻和后瞻组合,但始终匹配 |"field3"|"field4| 而不仅仅是 |"field4|

我需要查找 |" 的内容和一些没有管道的文本,以没有前导引号的管道结尾。

【问题讨论】:

  • 预期结果是什么?
  • 引用" 的目标是不允许包含管道|?如何区分字段中缺少的引号和管道?
  • 扩展的测试记录将是 ||field2|"field3"|"field4|"field5"|"fie""ld6|field7|"| 并且使用下面的每个人的帮助我能够使用正则表达式((?

标签: java regex etl


【解决方案1】:

按照正则表达式

(?<=\|)"(?=[^|]*(?<!")\|)

匹配一个",前面是文字|,并且其下一个|字符前面没有"

regex101

【讨论】:

  • 这行得通!我也试过这个,但我没有做嵌套的前瞻和后瞻。看起来这是关键谢谢
【解决方案2】:

这个正则表达式将找到所有| 之前没有"

(?<!")\|

所以你使用它:

String result = data.replaceAll("(?<!\")\\|", "\"|");

在此代码之后,您会将字符串替换为之前没有管道的所有|,到"|

【讨论】:

  • 请注意,我可以有一个不带引号的字段,这没关系
【解决方案3】:

代码

See regex in use here

("[^|"]*")|"([^|"]*\|)

替换:$1$2


结果

输入

|||"field3"|"field4|"field5"|||

输出

|||"field3"|field4|"field5"|||

说明

  • 匹配以下任意一项
    • ("[^|"]*") 将以下内容捕获到捕获组 1
      • " 按字面意思匹配
      • [^|"]* 匹配除集合|" 中的字符以外的任意字符任意次数
      • " 逐字逐句匹配
    • "([^|"]*\|)
      • " 按字面意思匹配
      • ([^|"]*\|) 将以下内容捕获到捕获组 2
        • [^|"]* 匹配除集合|" 中的字符以外的任何字符任意次数
        • \| 匹配 | 字面意思

【讨论】:

    【解决方案4】:

    您可以在正则表达式中使用否定类:

    str = str.replaceAll("\\|\"([^|]*[^\"|]\\|)", "$1");
    

    RegEx Demo

    正则表达式解释:

    • ":匹配双引号
    • |: 匹配管道字符
    • ([^"|]*[^"|]\|):后跟 0 个或多个不是管道的字符,后跟一个非管道、非引号字符,然后是管道。在第 1 组中也捕获此内容

    • 在替换中,只需使用 $1 对捕获的组 #1 进行反向引用即可获取字段值,而无需前导双引号。

    【讨论】:

    • 感谢这对我的示例有效,但在 ||field2|"field3"|"field4|"field5"||"fie""ld6||field7| 上失败了。预期结果将是 ||field2|"field3"|field4|"field5"||fie""ld6||field7|。
    • 这很容易解决。只需使用:str = str.replaceAll("\\|\"([^|]*[^\"|]\\|)", "|$1");
    • 另请注意,这个问题并不真正需要向前看和向后看。查看演示链接,这一步完成的工作要少得多。
    猜你喜欢
    • 2021-11-29
    • 1970-01-01
    • 1970-01-01
    • 2021-09-02
    • 2014-06-25
    • 1970-01-01
    • 2012-09-05
    • 2018-05-19
    • 1970-01-01
    相关资源
    最近更新 更多