我在这里需要速度.我有一个500mb大小的csv文件(实际上有很多csv,但我现在只考虑一个)我需要阅读第3列并从中选择唯一的字符串.我测试了以下方法,我发现只有awk是最快的
使用perl:
在上述所有方法中,解析csv大约需要500秒.
但如果我尝试使用awk做同样的事情,它将在近10秒内完成.
我仍然在学习我的脚步在Perl,最近我的激情向人们看到它的散列的电源后,成长了很多.但是这个问题让我退缩了.这是unix工具占上风的perl的一些限制吗?
我知道Text :: CSV是处理csv文件的最佳方式.但速度是我关注的问题,我可以保证我的csv没有任何嵌入式逗号或其他问题,只有Text :: CSV可以处理.
更新:发现我的问题
my %hash;
my $file = $ARGV[0] or die "Need input CSV $!\n";
open(my $fh,'<',$file) or die "Could not open the $file $!\n";
while(my $line = <$fh>)
{
chomp($line);
my $field2=(split /|/, $line)[2]; #I missed to quote the pipe delimiter
$hash{$field2}++;
}
print "$_\n" for keys %hash;
Run Code Online (Sandbox Code Playgroud)
另一个更新:发布并修复
我的csv被'|'分隔 我错过了引用它们.因此,执行时间显着减慢,而且它产生的输出是错误的,我没有注意到.引用分隔符后,脚本能够在大约18秒内完成,当我使用@Borodin逻辑限制字段分割时,执行时间进一步减少.我能达到与awk相同的速度.
我仍然发现Text :: CSV方法较慢,因为我的文件可以使用默认的分割方法,我将继续使用它.
我生成了一个包含10,000,000行的350 MiB文件,类似于:
part1,part2,data856801,part4,part5
Run Code Online (Sandbox Code Playgroud)
(其中第三列中的数字是100,000到999,999之间的随机值)并使用了自制的Perl 5.18.1:
time perl -n -a -F, -l -e '$a{$F[2]}++;
END { foreach $key (sort keys %a) {print "$key";} }' junk.data >junk.perl.output
Run Code Online (Sandbox Code Playgroud)
这花了大约34秒.没有sort,它花了大约33秒(我的时间有一些变化).系统提供的Perl 5.16.2的时间基本相同.
为了比较,使用BSD awk(20070501):
time awk -F, '{a[$3]++} END {for (key in a) print key}' junk.data > junk.awk.output
Run Code Online (Sandbox Code Playgroud)
这花了大约29秒,以未排序的顺序产生数据.GNU awk3.1.7花了大约15秒(令人印象深刻的更快).
只需使用cat或cp在文件上花费超过5秒钟.
所有过滤后的输出文件中都有899993行; 一致性很好.
因此,对于这项工作来说,Perl比awk我的机器稍慢,但不是50倍.我不确定在Perl脚本上可以进行多少优化; 我所写的内容非常简单粗暴.
测试:
awk20070501awk3.1.7我让iTunes在后台播放音乐,并在浏览器中输入,因此在测试运行时系统没有空闲.
使用Text :: CSV with Text :: CSV_XS和以下脚本,花了将近49秒:
#!/usr/bin/env perl
use strict;
use warnings;
use Text::CSV;
my %a;
my $csv = Text::CSV->new ( { binary => 1 } ) # should set binary attribute.
or die "Cannot use CSV: ".Text::CSV->error_diag ();
open my $fh, "<:encoding(utf8)", "junk.data" or die "junk.data: $!";
while ( my $row = $csv->getline( $fh ) )
{
$a{$row->[2]}++;
}
$csv->eof or $csv->error_diag();
close $fh;
print "$_\n" for keys %a;
Run Code Online (Sandbox Code Playgroud)
有趣的是,Borodin的脚本花了大约17秒,比Perl-as- awkmode操作快了很多.知道Perl是否设法优化分割是很有趣的,因为它知道它只需要第三个字段,而awk模式必须在每一行中分割五个字段(对于样本文件),即使只使用了第三个字段.
这与GNU awk时间非常相似.