固定長データ
Posted feedbacks - Perl
やっつけですがunpackを使った例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | #!/usr/bin/perl
use strict;
use warnings;
my $dat;
if (@ARGV) {
open $dat, shift or die;
} else {
$dat = \*STDIN;
}
my $bytes;
my @records;
for (1..500) {
read $dat, $bytes, 12 + 12 + 1 + 3 + 4 + 2;
my ($lname, $fname, $sex, $age, $year, $month) = unpack "A12A12A1A3A4A2", $bytes;
$lname =~ s/\s*$//;
$fname =~ s/\s*$//;
my %record = (last_name => $lname,
first_name => $fname,
sex => $sex,
age => $age + 0,
year => $year + 0,
month => $month + 0,
menues => []);
for (1..31) {
read $dat, $bytes, 2 + 500 + 500 + 500;
my ($day, $breakfast, $lunch, $dinner) = unpack "A2A500A500A500", $bytes;
$breakfast =~ s/^\s*|\s*$//;
$lunch =~ s/^\s*|\s*$//;
$dinner =~ s/^\s*|\s*$//;
push @{$record{menues}}, {day => $day + 0,
breakfast => $breakfast,
lunch => $lunch,
dinner => $dinner};
}
push @records, \%record;
}
#テスト出力
use Data::Dumper;
print Dumper @records;
|
ついでにテストデータ生成スクリプトを貼っておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #!/usr/bin/perl
use strict;
use warnings;
my @lnames = map { sprintf "%-12s", $_ } qw/Foo Bar Baz Jim Bob Beth Cathy/;
my @fnames =
map { sprintf "%-12s", $_ } qw/Hoge Fuga Piyo Jacson Page McDonald Hamond/;
my @sexes = qw/F M U/;
my @ages = map { sprintf "%03d", $_ } 0 .. 999;
my @dishes =
map { sprintf "%-500s", $_ }
qw/BaconEgg Coffee HamEgg BoiledEgg EggInBasket Udon Steak
SunnySideUp Onigiri Ramen/;
sub randomint { int rand shift }
for ( 1 .. 500 ) {
print $lnames[ randomint( scalar @fnames ) ],
$fnames[ randomint( scalar @lnames ) ],
$sexes[ randomint( scalar @sexes ) ], $ages[ randomint( scalar @ages ) ],
"200803";
for my $day ( 1 .. 31 ) {
$day = sprintf "%02d", $day;
print $day, $dishes[ randomint( scalar @dishes ) ],
$dishes[ randomint( scalar @dishes ) ],
$dishes[ randomint( scalar @dishes ) ];
}
}
|
どうも encoding まわりの扱いに自信がありません.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | use strict;
use warnings;
use Data::Dumper;
use constant ROWSIZE => 1536;
no encoding;
my @cols = qw( family_name four_name gender age year mon date
breakfast lunch dinner );
my $i = 0;
my @row = ();
print '(';
while(!eof STDIN){
my ($buf, %rec) = ("",());
read STDIN , $buf , ROWSIZE;
printf "do{%s}," , Dumper { map{
s/^\s+//; s/\s+$//;
( $cols[ $i++ % @cols] , $_ );
} unpack "A12A12A1A3A4A2A2A500A500A500" , $buf };
}
print ')';
|




Mymelo #6060() Rating5/7=0.71
固定長のデータが記載されたファイルを読み込むプログラムを作成してください。読み込んだデータは、複数の値を格納できるデータ型に格納してください。
ファイルには、すべて ascii 文字で以下のデータが格納されています。デリミタはなく、固定長で格納されています。レコードとレコードのあいだも改行はありません。
以上の形式のデータ500人分を読みこんで、データを複数の値を格納できるデータ型に格納してください。データに大して何か処理を行う必要はなく、すぐに破棄してかまいません。
この問題は、このようなファイルをどのように扱うかを知りたくて作成しました。
[ reply ]