如何在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命令行工具,它不需要我调用其他脚本环境或编写任何其他代码(!)
答案 0 :(得分:21)
csvtool非常好。可在Debian / Ubuntu中使用(apt-get install csvtool
)。例如:
csvtool namedcol Account,Cost input.csv > output.csv
有关使用提示,请参阅CSVTool manual page。
答案 1 :(得分:20)
我的FOSS CSV流编辑器CSVfix完全符合您的要求。有一个用于Windows的二进制安装程序,以及一个用于UNIX / Linux的可编译版本(通过makefile)。
答案 2 :(得分:9)
正如@Jonathan在评论中所建议的那样,python的模块提供了命令行工具csvfilter。它像剪切一样工作,但正确处理CSV列引用:
csvfilter -f 1,3,5 in.csv > out.csv
如果你有python(你应该),你可以像这样安装它:
pip install csvfilter
的更多信息
答案 3 :(得分:7)
我发现csvkit很有用,它基于python csv 模块,并且有很多选项可用于解析复杂的csv文件。
虽然看起来有点慢。当从具有5列的7GB csv中提取一个字段时,我得到4MB / s(100%cpu)。
从file.csv
csvcut -c 4 file.csv
答案 4 :(得分:5)
尝试crush-tools,他们非常善于操纵分隔数据。 这听起来就像你正在寻找的。 p>
答案 5 :(得分:3)
我也编写了一个名为csvprintf的工具(仅限UNIX)。它还可以在线方式转换为XML。
答案 6 :(得分:2)
我的直觉反应是在Python的csv模块周围写一个脚本包装器(如果还没有这样的话)。
答案 7 :(得分:2)
对于Python的csv
模块的超轻量级包装,您可以查看pluckr。
答案 8 :(得分:1)
这听起来像是awk的工作。
您很可能需要编写自己的脚本以满足您的特定需求,但this网站有一些关于如何执行此操作的对话。
您还可以使用剪切实用程序去除字段。
类似的东西:
cut -f 2,5,6 -d , filename
其中-f参数是您想要的字段,-d是您想要的分隔符。然后,您可以对这些结果进行排序,找到唯一的结果,或使用任何其他bash实用程序。关于使用命令行中的CSV文件,有一个很酷的视频here。只有一分钟左右,我来看看。
但是,我猜你可以用awk对cut实用程序进行分组,而不想使用它。我不知道你的本地bash命令究竟是什么意思,所以我仍然会建议它。
答案 9 :(得分:1)
ffe
是另一个很棒的工具。它要求您为大多数重要任务创建配置文件。好处是它非常灵活,可以处理其他工具无法实现的各种结构,逻辑和格式。
我喜欢使用csvtool
来快速完成工作,并将ffe
用于复杂的工作或需要经常重复的工作。
答案 10 :(得分:0)
快速谷歌显示似乎处理csv文件的awk script。
答案 11 :(得分:0)
Perl脚本(需要Text :: CSV_XS):
#!/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";
}
将其放入档案csvcut.pl
。
仅采用第3列和第4列的示例:
cat foo.csv | ./csvcut.pl --c 3 --c 4
这只会引用需要引用的列,所以如果输入列有“Bar”(带引号),它就会出现Bar(没有引号)。