我有一个很大的.csv文件(2 -300万条记录)。我需要连接前三个字段(带下划线)并将其附加到每个记录,然后我需要根据新字段和其他三个字段对文件进行排序。我可以做到这一点(目前我正在用一个4记录文件进行测试)--但我不确定如何以相同的.csv形式将它写回文件--而不是像Data::Dumper那样将每一行都格式化为一个单独的变量。这是我到目前为止的代码-我有几行打印(到屏幕)代码来看看它在做什么-
#!/usr/bin/perl/
use strict;
use warnings;
use Data::Dumper;
my $filename = '/testpath/test.csv';
#$filename = 'test.csv';
open my $FH, $filename
or die "Could not read from $filename <$!>, program halting.";
# Read the header line.
chomp(my $line = <$FH>);
my @fields = split(/,/, $line);
#print "Field Names:\n", Dumper(@fields), $/;
print Dumper(@fields), $/;
my @data;
# Read the lines one by one.
while($line = <$FH>) {
# split the fields, concatenate the first three fields,
# and add it to the beginning of each line in the file
chomp($line);
my @fields = split(/,/, $line);
unshift @fields, join '_', @fields[0..2];
push @data, \@fields;
}
close $FH;
print "Unsorted:\n", Dumper(@data); #, $/;
@data = sort {
$a->[0] cmp $b->[0] ||
$a->[20] cmp $b->[20] ||
$a->[23] cmp $b->[23] ||
$a->[26] cmp $b-> [26]
} @data;
open my $OFH, '>', '/testpath/parsedTest.csv';
print $OFH Dumper(@data);
close $OFH;
exit;我假设它在"print $OFH Dumper(@data);“行中,我需要将其重新格式化为原始格式。
我是个新手,所以请多多关照。
__________EDIT__________________________________
以下是测试.csv文件中的四行-第一行是标题记录:
STORE_NBR,CONTROL_NBR,LINE_NBR,SALES_NBR,QTY_MISTINT,REASON_CODE,MISTINT_COMM,SZ_CDE,TINTER_MODEL,TINTER_SERL_NBR,SPECTRO_MODEL,SPECTRO_SERL_NBR,EMP_NBR,TRAN_DATE,TRAN_TIME,CDS_ADL_FLD,PROD_NBR,PALETTE,COLOR_ID,INIT_TRAN_DATE,GALLONS_MISTINTED,UPDATE_EMP_NBR,UPDATE_TRAN_DATE,GALLONS,FORM_SOURCE,UPDATE_TRAN_TIME,SOURCE_IND,CANCEL_DATE,COLOR_TYPE,CANCEL_EMP_NBR,NEED_EXTRACTED,MISTINT_MQ_XTR,DATA_SOURCE,GUID,QUEUE_NAME,BROKER_NAME,MESSAGE_ID,PUT_TIME,CREATED_TS
1334,53927,1,100551589,1,6,Bad Shercolor Match,16,IFC 8112NP,01DX8005513,,,77,10/23/2015,95816,,OV0020001,,MANUAL,10/21/2015,1,0,,1,MAN,,CUST,,CUSTOM MATCH,0,TRUE,TRUE,O,5394A0E67FFF4D01A0D9AD16FA29ABB1,POS.MISTINT.V0000.UP.Q,PROD_SMISC_BK,414D512050524F445F504F533133333464EB2956052C0020,10/23/2015 10:45,10/23/2015 10:45
2525,67087,1,650462328,1,4,Tinted Wrong Product,14,IFC 8012NP,Standalone-5,,,11,10/23/2015,104314,,A91W00353,,,10/20/2015,0.25,0,,0.25,,,COMP,,CUSTOM MATCH,0,TRUE,TRUE,O,1AC5D8742D47435EA05343D57372AD32,POS.MISTINT.V0000.UP.Q,PROD_SMISC_BK,414D512050524F445F504F533235323531C2295605350020,10/23/2015 10:46,10/23/2015 10:47
1350,163689,1,650462302,1,3,Tinted Wrong Color,14,IFC 8012NP,06DX8006805,,,1,10/23/2015,104907,,A91W00351,COLOR,6233,10/23/2015,0.25,0,,0.5,ENG,,SW,,PALETTE,0,TRUE,TRUE,O,F1A072BCC548412FA22052698B5B0C28,POS.MISTINT.V0000.UP.Q,PROD_SMISC_BK,414D512050524F445F504F53313335307BC12956053C0020,10/23/2015 10:52,10/23/2015 10:52希望这篇文章不会读起来太费解。
发布于 2016-03-29 01:29:35
Data::Dumper输出的格式是有效的perl,对调试很好,但不适合写CSV文件。您可以手写CSV:
foreach my $row (@data) {
print $OFG join(',', @$row), "\n";
}但是您确实应该使用一个专门的模块,在本例中为Text::CSV,用于读取和写入CSV -它将处理所有边界情况(例如带有嵌入逗号的字段)。
大纲包含了一个很好的阅读和写作的例子;我在这里不再重复了。
发布于 2016-03-29 01:22:35
如果你只是把它存储在@data中,你也不需要重新构建它!
my @data;
while(my $line = <$FH>) {
chomp($line);
my @fields = split(/,/, $line);
push @data, [ "$line\n", join('_', @fields[0..2]), @fields[19, 22, 25] ];
}
@data = sort {
$a->[1] cmp $b->[1] ||
$a->[2] cmp $b->[2] ||
$a->[3] cmp $b->[3] ||
$a->[4] cmp $b->[4]
} @data;
print($OFH $_->[0]) for @data;如果您的输入不包含NULs,您甚至可以使用以下更快的方法:
print $OFH
map { /[^\0]*\z/g }
sort
map {
chomp;
my @fields = split /,/;
join("\0", join('_', @fields[0..2]), @fields[19, 22, 25], "$_\n")
}
<$FH>;但是,您可能应该使用合法的CSV解析器。
use Text::CSV_XS qw( );
my $csv = Text::CSV_XS->new({ binary => 1, auto_diag => 1 });
my @data;
while (my $row = $csv->getline($FH)) {
push @data, [ join('_', @$row[0..2]), $row ];
}
@data = sort {
$a->[0] cmp $b->[0] ||
$a->[1][19] cmp $b->[1][19] ||
$a->[1][22] cmp $b->[1][22] ||
$a->[1][25] cmp $b->[1][25]
} @data;
$csv->say($OFH, $_->[1]) for @data;以下是使用CSV解析器的快速方法:
use Text::CSV_XS qw( );
my $csv = Text::CSV_XS->new({ binary => 1, auto_diag => 2 });
print $OFH
map { /[^\0]*\z/g }
sort
map {
$csv->parse($_);
my @fields = $csv->fields();
join("\0", join('_', @fields[0..2]), @fields[19, 22, 25], $_)
}
<$FH>;发布于 2016-03-29 02:45:39
不幸的是,我无法使用Text::CVS_XS,因为它在我们的服务器上不可用-但确实发现添加这一行“打印”行是有效的-
open my $OFH, '>', '/swpkg/shared/batch_processing/mistints/parsedTest.csv';
print $OFH join(',', @$_), $/ for @data;
close $OFH; 用小文件测试没问题,现在就在实际文件上测试!
https://stackoverflow.com/questions/36267225
复制相似问题