首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Perl -使用Data::Dumper回写文件

Perl -使用Data::Dumper回写文件
EN

Stack Overflow用户
提问于 2016-03-29 01:14:56
回答 3查看 859关注 0票数 1

我有一个很大的.csv文件(2 -300万条记录)。我需要连接前三个字段(带下划线)并将其附加到每个记录,然后我需要根据新字段和其他三个字段对文件进行排序。我可以做到这一点(目前我正在用一个4记录文件进行测试)--但我不确定如何以相同的.csv形式将它写回文件--而不是像Data::Dumper那样将每一行都格式化为一个单独的变量。这是我到目前为止的代码-我有几行打印(到屏幕)代码来看看它在做什么-

代码语言:javascript
复制
#!/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文件中的四行-第一行是标题记录:

代码语言:javascript
复制
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

希望这篇文章不会读起来太费解。

EN

回答 3

Stack Overflow用户

发布于 2016-03-29 01:29:35

Data::Dumper输出的格式是有效的perl,对调试很好,但不适合写CSV文件。您可以手写CSV:

代码语言:javascript
复制
foreach my $row (@data) {
    print $OFG join(',', @$row), "\n";
}

但是您确实应该使用一个专门的模块,在本例中为Text::CSV,用于读取和写入CSV -它将处理所有边界情况(例如带有嵌入逗号的字段)。

大纲包含了一个很好的阅读和写作的例子;我在这里不再重复了。

票数 3
EN

Stack Overflow用户

发布于 2016-03-29 01:22:35

如果你只是把它存储在@data中,你也不需要重新构建它!

代码语言:javascript
复制
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,您甚至可以使用以下更快的方法:

代码语言:javascript
复制
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解析器。

代码语言:javascript
复制
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解析器的快速方法:

代码语言:javascript
复制
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>;
票数 2
EN

Stack Overflow用户

发布于 2016-03-29 02:45:39

不幸的是,我无法使用Text::CVS_XS,因为它在我们的服务器上不可用-但确实发现添加这一行“打印”行是有效的-

代码语言:javascript
复制
open my $OFH, '>', '/swpkg/shared/batch_processing/mistints/parsedTest.csv'; 
print $OFH join(',', @$_), $/ for @data; 
close $OFH; 

用小文件测试没问题,现在就在实际文件上测试!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36267225

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档