【问题标题】:Regex to match CSV file nested quotes正则表达式匹配 CSV 文件嵌套引号
【发布时间】:2011-03-01 11:15:17
【问题描述】:

我知道这已经讨论了一百万次了。我尝试在论坛中搜索并看到一些接近的正则表达式并尝试修改它们但无济于事。

假设 CSV 文件中有这样一行:

"123", 456, "701 "B" Street", 910
                 ^^^

是否有一个简单的正则表达式来检测 "B" (因为它是正常 CSV 引号中的一组非转义引号)并将其替换为 \"B\" 之类的东西?最终的字符串最终看起来像这样:

"123", 456, "701 \"B\" Street", 910

我们将不胜感激!

【问题讨论】:

标签: java regex csv


【解决方案1】:

相信我,你不想用正则表达式来做这件事。你想要像Java CSV Library 这样的东西。

【讨论】:

  • 是的,我同意。不幸的是,我是一个使用基于 StreamTokenizer 的解决方案的低级开发人员,很遗憾我不能放弃。但是,如果那些内部引号被转义,它会工作得很好。
  • @user361970 - 如果您有一个损坏的解决方案需要修复,当然您可以放弃它并做得更好。当然,我们不能在这里谈论超过 100 行代码。如果你的老板不这么说,把他送到 SO,我们可以向他解释为什么修补坏代码是个坏主意。
  • StreamTokenizer 更糟糕
【解决方案2】:

有很多库可以帮助您解析 CSV,但如果您出于学术原因想要使用正则表达式,这可能会有所帮助:

  • 带转义支持的引用字符串。 "(\\.|[^\\"])*"
  • 未加引号的字段:[^",]*
  • 分隔符:, *

我不使用 CSV 文件,所以我不确定“其他 csv 字段”的有效性(例如上面的匹配 456),或者 /, */ 是否是您想要的分隔符..

无论如何,结合以上内容将匹配一个字段和一个分隔符(或字符串的结尾):

(quotedstring|unquoted)(delimiter|$)

【讨论】:

    【解决方案3】:

    我会使用定制的 sed 表达式作为

    's/\(.*\),\(.*\),\(.*\)"\(.*\)\" \(.*\),\(.*\)/\1,\2,\3 \4 \5 \6/g'
    

    【讨论】:

    • 这可能是期中要走的路
    • 我将如何修改它以使用 \ 转义而不是替换为空字符串?
    • Simple 's/\(.*\),\(.*\),\(.*\)"\(.*\)\" \(.*\),\(.*\)/\1,\2,\3 \\\"\4\\" \5 \6/g' 请注意,\\ 将导致打印 \ 并且 " 将在 \4 周围打印一个 " 希望能回答它。
    • 我想我需要学习一些 sed 课程。我在 cygwin sed 中对其进行了测试:-e expression #1, char 58: invalid reference \6 on `s' command's RHS
    • 格式化在 sed 表达式之上搞砸了。看看我原来的答案,保持正则表达式部分不变..只需将 \4 更改为 \\\"\4\\"
    【解决方案4】:

    您的示例不是正确的 CSV:

    "123", 456, "701 "B" Street", 910
    

    这实际上应该是:

    "123", 456, "701 ""B"" Street", 910
    

    (当然,CSV 有很多变体,但由于大多数时候人们希望它与 excel 或 access 一起使用,我坚持使用 Microsoft 的定义。)

    因此,正则表达式可能如下所示:

    ".+("").+("").+"
    

    组(在括号中)将是您的双引号,其余的确保它们可以在另一组引号中找到。

    这涵盖了您需要的查找部分。替换部分取决于您正在编程的内容。

    【讨论】:

    • 不完全是。在 CSV 案例中,您正在寻找类似 @​​987654324@ 的模式:匹配由非引号或两个引号组成的标记。 .+ 无论如何都可能匹配单引号,而.+("").+("").+ 采用了一种过于具体的格式——它只允许两个引号,而+ 需要它们之前、之间和之后的字符。
    • 啊……没错。这就是我晚饭后如此近距离地回答的结果。我总是把我的优点和星号弄糊涂......
    【解决方案5】:
    (?<!^)(?<!",)(?<!\d,)"(?!,")(?!,\d)(?!$)(?!,-\d)
    

    我得到了这个工作,如果其他人正在寻找答案,我想我会发布它

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多