如何在Linux命令行上解析CSV文件?
做以下事情:
csvparse -c 2,5,6 filename
从所有行中提取第2,5和6列的字段。
它应该能够处理csv文件格式:http://tools.ietf.org/html/rfc4180这意味着引用字段并根据需要转义内部引号,因此对于包含3个字段的示例行:
field1,"field, number ""2"", has inner quotes and a comma",field3
所以,如果我请求上面一行的字段2,我得到:
field, number "2", has inner quotes and a comma
我很欣赏有很多解决方案,Perl,Awk(等)来解决这个问题,但我想要一个本机bash命令行工具,它不需要我调用其他脚本环境或编写任何其他代码(!)。
我的FOSS CSV流编辑器CSVfix完全符合您的要求。有一个用于Windows的二进制安装程序,以及一个用于UNIX / Linux的可编译版本(通过makefile)。
一个快速的谷歌揭示了一个似乎处理csv文件的csvtool
。
Perl脚本(需要Text :: CSV_XS):
ffe
把它放在awk script文件中。
仅采用第3列和第4列的示例:
#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long;
my @opt_columns;
GetOptions("column=i@" => \@opt_columns)
or die "Failed parsing options\n";
die "Must give at least one --column\n" if int(@opt_columns) == 0;
@opt_columns = map { $_-1 } @opt_columns; # convert 1-based to 0-based
use Text::CSV_XS;
my $csv = Text::CSV_XS->new ( { binary => 1 } );
open(my $stdin, "<-") or die "Couldn't open stdin\n";
open(my $stdout, ">-") or die "Couldn't open stdout\n";
while (my $row = $csv->getline($stdin)) {
my @nrow = @{$row}[@opt_columns];
$csv->print($stdout, \@nrow);
print "\n";
}
这将仅引用需要引用的列,因此如果输入列具有“Bar”(带引号),它将出现Bar(不带引号)。
csvtool非常好。可在Debian / Ubuntu(apt-get install csvtool
)中找到。例:
csvtool namedcol Account,Cost input.csv > output.csv
有关使用技巧,请参阅CSVTool manual page。
正如@Jonathan在评论中所建议的那样,python的模块提供了命令行工具csvfilter。它像剪切一样工作,但正确处理CSV列引用:
csvfilter -f 1,3,5 in.csv > out.csv
如果你有python(你应该),你可以像这样安装它:
pip install csvfilter
我发现csvkit很有用,它基于python csv模块,并且有很多选项可用于解析复杂的csv文件。
虽然看起来有点慢。当从具有5列的7GB csv中提取一个字段时,我得到4MB / s(100%cpu)。
从file.csv
提取第4列
csvcut -c 4 file.csv
试试crush-tools,他们非常善于操纵分隔数据。这听起来就像你正在寻找的。
我也写了一个这样的工具(仅限UNIX),名为csvprintf。它还可以以在线方式转换为XML。
我的直觉反应是围绕Python的csv模块编写一个脚本包装器(如果还没有这样的话)。
对于Python qazxsw poi模块的超轻量级包装,您可以查看qazxsw poi。