CSV 文件处理 - 删除引号并用制表符替换逗号分隔符

CSV 文件处理 - 删除引号并用制表符替换逗号分隔符

需要使用 shell 命令转换分隔文件。接收到的输入文件有两种变体,一种带有双引号,另一种不带引号,并且两个文件都以逗号作为分隔符。要求是用 TAB 替换逗号并删除引号(如果文件有双引号),否则只需替换逗号。如果文件的字段也包含在转换时需要忽略的逗号,则文件将带有引号发送。 单个命令应该在 RHEL 6.x 环境上的 Awk 3.x 中有效。

例如。带双引号的文件1:

"Jhon","Carpenter","CA,TX,NJ"
"Mike","Painter","WA,GA,MI"

转换后应该用制表符分隔:

Jhon   Carpenter   CA,TX,NJ 
Mike   Painter     WA,GA,MI 

例如。文件2不带双引号:

EMP1,123456,CA 
EMP2,456789,TX 

转换后应该用制表符分隔:

EMP1 123456   CA 
EMP2   456789   TX

答案1

使用csvkit

$ csvformat -T file1.csv
Jhon    Carpenter       CA,TX,NJ
Mike    Painter WA,GA,MI

$ csvformat -T file2.csv
EMP1    123456  CA
EMP2    456789  TX

的输出file1.csv看起来有点不对劲,但这只是因为选项卡没有正确排列。所有列之间都有一个选项卡。

CSVKit 是一个基于 Python 的工具箱,包含各种 CSV 相关的 shell 实用程序。它可以进行正确的 CSV 解析,并可用于查询、格式化和转换 CSV 文件。

例如,如果第一个文件有正确的标头,那么将其转换为 JSON 就很简单

$ csvjson file1.csv
[{"First": "Jhon", "Last": "Carpenter", "Stuff": "CA,TX,NJ"}, {"First": "Mike", "Last": "Painter", "Stuff": "WA,GA,MI"}]

答案2

这个简短的sed脚本可以处理这两种类型的文件(甚至可以处理包含第一种和第二种类型的混合文件):

sed '/"/!s/,/\t/g;s/","/\t/g; s/"//g'

由于它不会对不循环的表达式进行分组,因此它应该比您的脚本快得多。

你似乎有 GNU sed,所以\t可以工作,否则使用文字 TAB 代替。

答案3

几种做法:

对于file1(带双引号):

--awk方法:

awk -F'"' '{ r=""; for(i=1;i<NF;i++) 
     if ($i~/^[[:alnum:]]/) r=(r!="")? r OFS $i : $i; print r }' OFS='\t' file1

--sed方法:

sed 's/","/\t/g; s/"//g;' file1

输出(两种方法):

Jhon    Carpenter   CA,TX,NJ
Mike    Painter WA,GA,MI

----------

对于file2(不带双引号) - 应用tr命令就足够了:

tr ',' '\t' <file2

输出:

EMP1    123456  CA
EMP2    456789  TX

----------

条件的统一方法“相同的命令应该足以满足两种文件类型”:

awk -v quoted=$(grep -cm1 '"' file1) 'BEGIN{ FS=(quoted)? "\"" : ","; }
     { r=""; for(i=1;i<=NF;i++) if(!quoted || $i~/^[[:alnum:]]/) r=(r!="")? r OFS $i : $i; 
             print r }' OFS='\t' file1

答案4

CSV 数据需要适当的 CSV 解析器。我喜欢库萨拉南达的回答。您还可以使用像 Ruby 这样带有 csv 模块的语言:

ruby -rcsv -e '
  out = CSV.new($stdout, {:col_sep => "\t"})
  CSV.foreach(ARGV.shift) {|row| out << row} 
' file1.csv

相关内容