34 python perl text-processing csv
我有许多大型 CSV 文件,并希望它们采用 TSV(制表符分隔格式)。复杂的是CSV文件的字段中有逗号,例如:
A,,C,"D,E,F","G",I,"K,L,M",Z
Run Code Online (Sandbox Code Playgroud)
预期输出:
A C D,E,F G I K,L,M Z
Run Code Online (Sandbox Code Playgroud)
(中间的空格是“硬”标签)
我在这台服务器上安装了 Perl、Python 和 coreutils。
One*_*eer 49
添加到名为 的文件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))
Run Code Online (Sandbox Code Playgroud)
$ echo 'A,,C,"D,E,F","G",I,"K,L,M",Z' | ./csv2tab
A C D,E,F G I K,L,M Z
Run Code Online (Sandbox Code Playgroud)
$ ./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
Run Code Online (Sandbox Code Playgroud)
Nei*_*gan 28
使用csvkit
(Python),例如:
$ csvformat -T in.csv > out.txt
Run Code Online (Sandbox Code Playgroud)
使用正确的 CSV 和 TSV 引用和转义进行流式传输
它在 apt 和其他包管理器中
tri*_*eee 22
为了好玩,sed
。
sed -E 's/("([^"]*)")?,/\2\t/g' file
Run Code Online (Sandbox Code Playgroud)
如果您sed
不支持-E
,请尝试使用-r
。如果您sed
不支持\t
文字制表符,请尝试放置文字制表符(在许多 shell 中,ctrl- v tab)或在 Bash 中,使用$'...'
C 样式字符串(在这种情况下,\2
需要将反斜杠加倍)。如果要保留引号,请使用\1
而不是\2
(在这种情况下,内对括号没有用,可以删除)。
如果您sed
不支持-E
或-r
,请尝试
sed -E 's/("([^"]*)")?,/\2\t/g' file
Run Code Online (Sandbox Code Playgroud)
如果\t
不支持,可能再次进行相同的调整。
这不会尝试处理双引号内的转义双引号;一些 CSV 方言通过将双引号 (sic) 加倍来支持这一点。
ste*_*ver 15
一种选择可能是 perl 的Text::CSV模块,例如
perl -MText::CSV -lne 'BEGIN { $csv = Text::CSV->new() }
print join "\t", $csv->fields() if $csv->parse($_)
' somefile
Run Code Online (Sandbox Code Playgroud)
展示
echo 'A,,C,"D,E,F","G",I,"K,L,M",Z' |
perl -MText::CSV -lne 'BEGIN { $csv = Text::CSV->new() }
print join "\t", $csv->fields() if $csv->parse($_)
'
A C D,E,F G I K,L,M Z
Run Code Online (Sandbox Code Playgroud)
小智 8
perl -lne '
my $re = qr/,(?=(?:[^"]*"[^"]*")*(?![^"]*"))/;
print join "\t", map { s/(?<!\\)"//gr =~ s/\\"/"/gr } split $re;
'
Run Code Online (Sandbox Code Playgroud)
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
}'
Run Code Online (Sandbox Code Playgroud)
结果:
A C D,E,F G I K,L,M Z
Run Code Online (Sandbox Code Playgroud)
我编写了一个开源的 CSV 到 TSV 转换器来处理所描述的转换。它非常快,如果持续需要转换大型 CSV 文件,可能值得一看。该工具是eBay 的 TSV 实用程序工具包(此处为csv2tsv 文档)的一部分。默认选项足以满足所描述的输入:
$ csv2tsv file.csv > file.tsv
Run Code Online (Sandbox Code Playgroud)
将 CSV 转换为 TSV 时的一个考虑因素是处理数据中的字段和记录分隔符(逗号和换行符)。CSV 使用转义语法。如果目标是使用输出与Unix工具一样cut
,awk
等等,输出需要自由逃逸。当数据中包含分隔符时,此处列出的大多数解决方案都会生成 CSV 样式的转义符。csv2tsv
与其他解决方案的不同之处在于它产生没有逃逸的 TSV。有关详细信息,请参阅文档。
要查看特定解决方案的作用,请转换数据中包含逗号、制表符、引号和换行符的 CSV。例如:
$ echo $'Line,Field1,Field2\n1,"Comma: |,|","Quote: |""|"\n"2","TAB: |\t|","Newline: |\n|"' | <conversion-script-or-command>
Run Code Online (Sandbox Code Playgroud)
生成转义的解决方案将在包含引号、换行符或制表符的字段周围放置双引号。
热核苍蝇拍解决方案必须使用 libreoffice。虽然https://ask.libreoffice.org/en/question/19042/is-is-possible-to-convert-comma-separated-value-csv-to-tab-separated-value-tsv-via-headless-mode /表明这是不可能的,但它是错误的(或者只是过时了?)并且以下命令适用于我的 5.3.:
loffice "-env:UserInstallation=file:///tmp/LibO_Conversion" --convert-to csv:"Text - txt - csv (StarCalc)":9,34,UTF8 --headless --outdir some/path --infilter='csv:44,34,UTF8' *.csv
env
可以跳过该参数,但这样文档就不会出现在您最近的文档中。
如果您拥有或可以安装该csvtool
实用程序:
csvtool -t COMMA -u TAB cat in.csv > out.ctv
Run Code Online (Sandbox Code Playgroud)
请注意,由于某种原因csvtool
没有手册页,但csvtool --help
会打印几百行文档。
使用mlr
几乎是简洁的,但禁用标头需要很长的选项:
mlr --c2t --implicit-csv-header --headerless-csv-output cat file.csv
Run Code Online (Sandbox Code Playgroud)
输出:
A C D,E,F G I K,L,M Z
Run Code Online (Sandbox Code Playgroud)