需要使用 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