2016-03-28 15 views
1

大きな.csvファイル(2〜300万レコード)があります。最初の3つのフィールド(下線)を連結して各レコードに追加する必要があります。その新しいフィールドと他の3つのフィールドに基づいてファイルをソートする必要があります。私はそれを行うことができます(今は4レコードファイルでテストしています)。しかし、Data :: Dumperフォーマットの代わりに、同じ.csv形式でファイルに書き戻す方法がわかりません行は別の変数として扱われます。私はそれがやっているものを見るために行(画面に)印刷のカップルを持っている - - ここでのコードは、私がこれまで持っているPerl - 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; 

私はそれが「印刷$ OFHダンパ(@data)でだと仮定しています。 "私はそれを元の形式に戻す必要があります。

私は初心者ですので、親切にしてください。ここで

__________EDIT__________________________________

テスト.csvファイルからの4行がある - 最初の行はヘッダレコードである:読むにはあまりにも複雑ではありません

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 

希望。

+0

4レコードの入力サンプルを表示して、それを出力にどのようにフォーマットしたいのですか?おそらく我々はそれを達成するための他のアイデアを持っているでしょう。 – PerlDuck

+4

あなたは適切なCSVモジュール(すなわち[Text :: CSV](https://metacpan.org/pod/Text::CSV) CSVデータの分解。私がリンクしているページにはたくさんの例があります。あなたが行う必要があることを正確に示します。 –

+0

@PerlDog - 上記の4行を追加しました。 – BigRedEO

答えて

2

@dataに保存しておけば、回線を再構築する必要はありません!

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パーサーを使用する必要があります:あなたの入力がNULsが含まれていなかった場合は

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; 

は、あなたも次のように高速なアプローチを使用することができます。

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>; 
+0

すぐにすべての素晴らしい答えに圧倒される! Text :: CSV_XSが私たちのサーバーで利用可能かどうかを確認する必要があります。 – BigRedEO

+0

そうでない場合は、インストールしてください。特別な権限が必要なのではない。 – ikegami

2

Data::Dumperは有効なperlのあるフォーマットを出力し、デバッグのためではなく、CSVファイルを書き込むために良いです。 あなたが手でCSVを書くことができます:

foreach my $row (@data) { 
    print $OFG join(',', @$row), "\n"; 
} 

が、CSVを読み書きするための両方あなたは本当に、この場合Text::CSVには、専門的なモジュールを使用する必要があります - それはすべての境界ケースを処理するようでフィールドとして(埋め込みコンマ)。

概要には、読み書きの両方の良い例が含まれています。私はここでこれを繰り返さない。

0

は、それが当社のサーバー上で利用できなかったので、残念ながら、:: CVS_XSテキストを使用することができませんでした - しかし、このシングル「印刷」の行が働い追加見つけた -

open my $OFH, '>', '/swpkg/shared/batch_processing/mistints/parsedTest.csv'; 
print $OFH join(',', @$_), $/ for @data; 
close $OFH; 

は小さなファイルで罰金アウトテスト済み実際のファイルをテストするようになりました!

+0

あなたのサーバにインストールされていないという理由だけで(証明された)モジュールを使用せず、独自の(潜在的にバグの多い)コードを書くことは、perlの開発を行う方法ではありません。サーバーにインストールする方法を見つける。 – mscha

関連する問題