假设我有一个这样的 csv 文件
a,b,c
1,"drivingme,mad",2
我想把它转换成 TSV
a<tab>b<tab>c
1<tab>drivingme,mad<tab>2
虽然我可以编写一些 Python 代码来做到这一点。我发现这很慢。即使行数达到数百万,是否有更好的 awk、sed 或 perl 方式非常快?
我需要这样做,因为我无法使用上述 csv 将 CSV 文件导入 SQLite 数据库,因为 SQLite 的 csv 导入功能有限。
Text::CSV_XS
(XS 是该模块的 C 版本,比原生 Perl Text::CSV 更快)是通常选择的工具。它
轻松处理带引号(和包含逗号)的字段
可用于阅读和写作
可以在分隔符之间切换,这样您就可以使用 TAB 来创建写入器对象。
示例(无错误处理):
my $csv_in = Text::CSV_XS->new ({ binary => 1 });
my $csv_out = Text::CSV_XS->new ({ binary => 1, sep_char => "\t", eol => "\n" });
open my $fh_in, "<", "file_in.csv" or die "file_in.csv: $!";
open my $fh_out, ">", "file_out.csv" or die "file_out.csv: $!";
while (my $row = $csv_in->getline($fh_in)) {
$csv_out->print ($fh_out, $row)
}
close $fh_in;
close $fh_out;
如果您有GNU awk
(4.0 或更高版本),您可以使用以下单行代码:
$ awk '{$1=$1;gsub(/"/,"")}1' FPAT='([^,]+)|(\"[^\"]+\")' OFS='\t' file
a b c
1 drivingme,mad 2
不需要 Text::CSV。Text::ParseWords是标准 Perl 发行版的一部分。
#!/usr/bin/perl
use strict;
use warnings;
use Text::ParseWords;
while (<>) {
print join "\t", parse_line(',', 0, $_);
}
将其称为 Unix 过滤器,如下所示:
$ ./csv2tsv < test.csv > test.tsv
对于大型 CSV 文件,我使用Parse::CSV。此外,您可以结合DBI + DBD::SQLite将已解析的行从 CSV 插入您的 SQLite 数据库
这可能对您有用(GNU sed):
sed -r ':a;s/(("[^"]*",)*"[^",]+),/\1\n/;ta;s/"//g;y/,\n/\t,/' file
用 's替换,
's within "
' \n
s。然后删除"
's 并将,
's and \n
's 翻译成\t
's and ,
's。