【问题标题】:How to escape double quotes inside CSV?如何在 CSV 中转义双引号?
【发布时间】:2018-12-05 08:20:00
【问题描述】:

我目前有几个 csv 文件,我无法控制它们的创建方式。不用说...它们格式不正确,不符合 RFC 4180。

示例输入:gist

",0000000000000000";"0";"1115S021121-12-1/2"M"
",0000000000000000";"0";"1115S021122-12-1/2"M"
",0000000000000000";"0";"1115S021123-12-1/2"M"
",0000000000000000";"0";"1115S021124-12-1/2"M"
"1";"1";"EXAMPLE_RANDOM" .    STRING"
"2,0000000000000000";"2";"this;can"also happen"

想要的:

",0000000000000000";"0";"1115S021121-12-1/2""M"

我一直在尝试通过使用正则表达式运行 sed 来修复它。但是我只有 regex 的基本知识,sed 不想在我的尝试中表现得很好。

有人可以帮我避开双引号内的英寸引号“吗? 我知道这样的解决方案只有 99%,我只能依靠以下事实。

  • 分隔符是;
  • 附件是“
  • " 可以在引用的文本字段中出现多次。

这意味着一个;或 " 可能出现在引用的字段中。 有人可以帮我把“换成”吗?

我尝试将几个stackoverflow帖子的正则表达式结合起来。

 sed -E "s/[^\"](?<!;)\"(?!;|$)/\1"/g" $filename.test2   -> error
 sed "s/[^\"](?<!;)(\")(?!;|$)/\1/g" $filename.test2    -> error 
 ... about 10 more variations, some even without errors but no replaced strings.

如果有人有除正则表达式之外的其他解决方案,我们非常感谢任何帮助!

编辑:感谢@choroba perl wizzard。以下修复了文件。

 cat $filename.test | perl -pe 's/(?<=[^;])"(?=[^;])/""/g' >  $filename.test2

【问题讨论】:

  • 我可以解析 ",0000000000000000";"0";"1115S021121-12-1/2""M"
  • 输入中是否有已正确转义的双引号?
  • 输入文件中暂时没有双引号。但是,如果它们应该发生,它们也需要被转义。所以这总共有4个报价。 """"
  • 三引号呢?比如",00000000"""00000000"。应该怎么办?
  • 不知道为什么这被标记为go

标签: regex unix sed


【解决方案1】:

Perl 的环视断言助你一臂之力!

perl -pe 's/(?<=[^;])"(?=[^;\n])/""/g' 

即如果" 前面没有; 并且后面没有;,则将其替换为""

【讨论】:

  • 你这个野蛮的魔法师!这很好用!我会更新我的问题。非常感谢,我为此浪费了很多时间。
  • 它在末尾添加了额外的"",预期输出中没有。
  • @stack0114106:已更新。只需将\n 添加到前瞻中即可。
【解决方案2】:
$ perl -MText::CSV_XS=csv -wE'csv(in=>csv(in=>"test.csv",sep=>";",allow_loose_quotes=>1,allow_loose_escapes=>1),always_quote=>1)'
",0000000000000000","0","1115S021121-12-1/2""M"
",0000000000000000","0","1115S021122-12-1/2""M"
",0000000000000000","0","1115S021123-12-1/2""M"
",0000000000000000","0","1115S021124-12-1/2""M"
"1","1","EXAMPLE_RANDOM"" .    STRING"
"2,0000000000000000","2","this;can""also happen"

正如 choroba 所说,使用“;”也作为输出 sep:

$ perl -MText::CSV_XS=csv -wE'csv(in=>csv(in=>"test.csv",sep=>";",allow_loose_quotes=>1,allow_loose_escapes=>1),always_quote=>1,sep=>";")'
",0000000000000000";"0";"1115S021121-12-1/2""M"
",0000000000000000";"0";"1115S021122-12-1/2""M"
",0000000000000000";"0";"1115S021123-12-1/2""M"
",0000000000000000";"0";"1115S021124-12-1/2""M"
"1";"1";"EXAMPLE_RANDOM"" .    STRING"
"2,0000000000000000";"2";"this;can""also happen"

应要求添加的说明:

Text::CSV_XS 是一个 perl 模块,可以非常灵活地解析和生成 CSV。使用选项/属性来允许格式错误的 CSV。

  1. csv (in => "file.csv", ...) 将文件读入内部结构

  2. sep => ";"将分隔符设置为“;”而不是默认的“,”

  3. allow_loose_quotes => 1 和 allow_loose_escapes => 1 可以读取不正确的 CSV 并接受未转义的嵌套引号

  4. csv()返回对内部结构的引用,对生成输出csv的外层csv调用有效(in => csv(in => "file.csv")

  5. 最后两个参数将 sep 设置为“;”也用于输出并导致所有字段都被引用,因为 OP 需要

有关所有选项和示例,请参阅 https://metacpan.org/module/Text::CSV_XS

在脚本中格式化,它可能看起来像

use Text::CSV_XS qw( csv );

csv (                    # Outer function
    always_quote => 1,   # Quote all field
    sep          => ";", # Use ; instead of ,
    in           =>      # Input
        csv (            #   comes from inner function
            in                  => "test.csv", # a file
            sep                 => ";",        # ; instead of ,
            allow_loose_quotes  => 1,          # allow ,"foo"bar",
            allow_loose_escapes => 1,          # idem
            )
    );

【讨论】:

  • Text::CSV_XS 是一个 perl 模块,可以非常灵活地解析和生成 CSV。使用选项/属性来允许格式错误的 CSV。
  • 加到答案的小伙伴中..稍微解释一下就更容易理解了
猜你喜欢
  • 1970-01-01
  • 2011-04-19
  • 1970-01-01
  • 2013-07-22
  • 1970-01-01
  • 2020-02-21
  • 2021-07-30
相关资源
最近更新 更多