仅在逗号分隔的文件中删除引号之间的逗号

mtk*_*mtk 25 sed awk text-processing csv

我有一个用逗号 ( ,)分隔的输入文件。有一些用双引号括起来的字段中包含逗号。这是示例行

123,"ABC, DEV 23",345,534.202,NAME
Run Code Online (Sandbox Code Playgroud)

我需要删除双引号和双引号内出现的所有逗号。所以上面的行应该被解析为如下所示

123,ABC DEV 23,345,534.202,NAME
Run Code Online (Sandbox Code Playgroud)

我尝试了以下使用sed但没有给出预期的结果。

sed -e 's/\(".*\),\(".*\)/\1 \2/g'
Run Code Online (Sandbox Code Playgroud)

任何快速的运用了sedawk或者任何其他Unix工具吗?

Tho*_*hor 37

如果引号是平衡的,您将需要删除每个其他引号之间的逗号,这可以表示为awk

awk -F'"' -v OFS='' '{ for (i=2; i<=NF; i+=2) gsub(",", "", $i) } 1' infile
Run Code Online (Sandbox Code Playgroud)

输出:

123,ABC DEV 23,345,534.202,NAME
Run Code Online (Sandbox Code Playgroud)

解释

-F"品牌在awk分离的双引号标志线,这意味着所有其他领域将是引号之间的文本。for 循环gsub在所有其他字段上运行,全局替换的缩写,用空( ",")替换逗号( "")。所述1在端调用默认代码块:{ print $0 }

  • 这种方法有一个问题:有时 csv 有跨越几行的行,例如:`prefix,"something,otherthing[newline]something , else[newline]3rdline,and,things",suffix`(即:几行,和嵌套的“,”在多行双引号中的任何地方:应该重新加入整个 `"...."` 部分,并且应该替换/删除里面的 `,` ... ) :您的脚本将看不到在这种情况下成对双引号,并且解决起来并不容易(需要“重新加入”处于“开放”(即奇数)双引号中的行...+如果还有转义`\"` *在字符串中) (2认同)

F. *_*uri 7

有一个很好的回应,只需一次使用 sed循环

echo '123,"ABC, DEV 23",345,534,"some more, comma-separated, words",202,NAME'|
  sed ':a;s/^\(\([^"]*,\?\|"[^",]*",\?\)*"[^",]*\),/\1 /;ta'
123,"ABC  DEV 23",345,534,"some more  comma-separated  words",202,NAME
Run Code Online (Sandbox Code Playgroud)

解释:

  • :a; 是进一步分支的标签
  • s/^\(\([^"]*,\?\|"[^",]*",\?\)*"[^",]*\),/\1 / 可以包含 3 个封闭部分
    • first the 2nd:[^"]*,\?\|"[^",]*",\?匹配一个不包含双引号的字符串,可能后跟一个逗号一个由两个双引号括起来的字符串,没有逗号,可能后跟一个逗号。
    • 而第一个RE 部分由与前面描述的第 2 部分一样多的重复组成,然后是 1 个双引号和一些字符,但没有双引号,也没有逗号。
    • 第一个 RE 部分后跟一个昏迷。
    • 注意,不需要触及该行的其余部分
  • ta将循环到:a上一个s/命令是否做了一些更改。

循环完成后,您甚至可以添加s/ */ /g

echo '123,"ABC, DEV 23",345,534,"some more, comma-separated, words",202,NAME'|
    sed ':a;s/^\(\([^"]*,\?\|"[^",]*",\?\)*"[^",]*\),/\1 /;ta;s/  */ /g'
Run Code Online (Sandbox Code Playgroud)

将抑制双空格:

123,"ABC DEV 23",345,534,"some more comma-separated words",202,NAME
Run Code Online (Sandbox Code Playgroud)


use*_*332 5

还可以处理平衡引号之间的多个逗号的通用解决方案需要嵌套替换。我在 perl 中实现了一个解决方案,它处理给定输入的每一行,并且只在每对其他引号中替换逗号:

perl -pe 's/ "  (.+?  [^\\])  "               # find all non escaped 
                                              # quoting pairs
                                              # in a non-greedy way

           / ($ret = $1) =~ (s#,##g);         # remove all commas within quotes
             $ret                             # substitute the substitution :)
           /gex'
Run Code Online (Sandbox Code Playgroud)

或者简而言之

perl -pe 's/"(.+?[^\\])"/($ret = $1) =~ (s#,##g); $ret/ge'
Run Code Online (Sandbox Code Playgroud)

您可以通过管道将要处理的文本传递给命令,也可以将要处理的文本文件指定为最后一个命令行参数。