Python

Python

我有许多大型 CSV 文件,希望它们采用 TSV(制表符分隔格式)。复杂的是 CSV 文件的字段中有逗号,例如:

 A,,C,"D,E,F","G",I,"K,L,M",Z

预期输出:

 A      C   D,E,F   G   I   K,L,M   Z

(其中之间的空格是“硬”选项卡)

我已在此服务器上安装了 Perl、Python 和 coreutils。

答案1

Python

添加到名为 的文件csv2tab,并使其可执行

touch csv2tab && chmod u+x csv2tab

添加到它

#!/usr/bin/env python
import csv, sys
csv.writer(sys.stdout, dialect='excel-tab').writerows(csv.reader(sys.stdin))

试运行

$ echo 'A,,C,"D,E,F","G",I,"K,L,M",Z' | ./csv2tab                     
A       C   D,E,F   G   I   K,L,M   Z

$ ./csv2tab < data.csv > data.tsv && head data.tsv                                                   
1A      C   D,E,F   G   I   K,L,M   Z
2A      C   D,E,F   G   I   K,L,M   Z
3A      C   D,E,F   G   I   K,L,M   Z

答案2

使用csvkit(Python),例如:

$ csvformat -T in.csv > out.txt

是否进行流式传输,并使用正确的 CSV 和 TSV 引用和转义

它位于 apt 和其他包管理器中

答案3

为了娱乐,sed

sed -E 's/("([^"]*)")?,/\2\t/g' file

如果您sed不支持-E,请尝试使用-r。如果您sed不支持\t文字制表符,请尝试放置文字制表符(在许多 shell 中为ctrl- v tab)或在 Bash 中使用C 样式字符串(在这种情况下,需要加倍$'...'反斜杠)。\2如果你想保留引号,请使用\1not \2(在这种情况下,内部一对括号没有用,可以删除)。

如果您sed不支持-E-r,请尝试

sed 's/\("\([^"]*\)"\)\?,/\2\t/g' file

\t如果不支持,可能会再次使用上面建议的调整。

为了获得更多乐趣,这里有与 Bash“here-string”语法相同的内容,只是为了演示它的样子。请注意我们想要接收的文字反斜杠sed现在是如何加倍的:

sed $'s/\\("\\([^"]*\\)"\\)\\?,/\\2\t/g' file

这不会尝试处理双引号内的转义双引号;某些 CSV 方言通过加倍双引号 (sic) 来支持这一点。

答案4

珀尔

perl -lne '
   my $re = qr/,(?=(?:[^"]*"[^"]*")*(?![^"]*"))/;
   print join "\t", map { s/(?<!\\)"//gr =~ s/\\"/"/gr } split $re;
'

awk

awk -v Q=\" -v FPAT="([^,]*)|(\"[^\"]+\")" -v OFS="\t" '{
   for (i=1; i<=NF; ++i)
      if ( substr($i, 1, 1) == Q )
         $i = substr($i, 2, length($i) - 2)
   print $1, $2, $3, $4, $5, $6, $7, $8
}'

结果:

A               C       D,E,F   G       I       K,L,M   Z

相关内容