如何在Linux命令行上解析CSV文件?

时间:2009-06-30 11:16:03

标签: linux unix csv

如何在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命令行工具,它不需要我调用其他脚本环境或编写任何其他代码(!)

12 个答案:

答案 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

https://github.com/codeinthehole/csvfilter/

的更多信息

答案 3 :(得分:7)

我发现csvkit很有用,它基于python csv 模块,并且有很多选项可用于解析复杂的csv文件。

虽然看起来有点慢。当从具有5列的7GB csv中提取一个字段时,我得到4MB / s(100%cpu)。

file.csv

中提取第4列
csvcut -c 4 file.csv

答案 4 :(得分:5)

尝试crush-tools,他们非常善于操纵分隔数据。 这听起来就像你正在寻找的。

答案 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(没有引号)。

相关问题