package Text::CSV::BulkData; use strict; use vars qw($VERSION); our $VERSION = '0.05'; use Carp; sub new { my ($class, $output_file, $format) = @_; bless { output_file => $output_file, format => $format, residue_loop => 1, }, $class; } sub set_residue_loop_off { my ($self, $output_file) = @_; $self->{residue_loop} = 0; return $self; } sub set_output_file { my ($self, $output_file) = @_; $self->{output_file} = $output_file; return $self; } sub set_format { my ($self, $format) = @_; $self->{format} = $format; return $self; } sub set_pattern { my $self = shift; $self->{pattern} = shift; return $self; } sub set_start { my ($self, $start) = @_; $self->{start} = $start; return $self; } sub set_end { my ($self, $end) = @_; $self->{end} = $end; return $self; } sub initialize { my $self = shift; my $output_file = $self->{output_file}; unlink $output_file or croak $! if -f $output_file; return $self; } sub make { my $self = shift; my ($output_file, $start, $end, $format, $pattern ) = ( $self->{output_file}, $self->{start}, $self->{end}, $self->{format}, $self->{pattern} ); my $debug_ary_ref; open FH, ">> $output_file" or croak $!; for (my $i = $start; $i <= $end; $i++){ my @input = (); for (my $j = 0; $j < ($format =~ s/%/%/g); $j++) { my $pattern = $$pattern[$j]; if ( ! defined $pattern ) { push @input, $i; next; } push @input, $self->_calculate($pattern, $i, 0); } $self->{debug} ? push @$debug_ary_ref, sprintf $format, @input : printf FH $format, @input; } close FH; $self->{debug} ? return $debug_ary_ref : return $self; } sub _calculate { my ($self, $pattern, $i, $flag) = @_; if ( ! $flag && $self->_is_recursive_start($pattern) ) { $pattern =~ m{^(\d+)[^0-9]}; $self->{pattern} = $pattern; $self->{before} = $1; $pattern =~ s{^\d+([^0-9])}{$1}; return $self->_calculate($pattern, $i, 1); } if ( $pattern =~ m{\*(\d+)} ) { if ( $flag eq 1) { my $res = $self->{before} * $1; $res = $self->_recursive_calc($res); $pattern = $self->_return_substituted('^\d+\*\d+', $res); } else { my $res = $i * $1; $pattern =~ s{\*\d+}{$res}; } $self->_calculate($pattern, $i, 0); } elsif ( $pattern =~ m{/(\d+)} ) { if ( $flag eq 1) { my $res = int($self->{before} / $1); $res = $self->_recursive_calc($res); $pattern = $self->_return_substituted('^\d+/\d+', $res); } else { my $res = int($i / $1); $pattern =~ s{/\d+}{$res}; } $self->_calculate($pattern, $i, 0); } elsif ( $pattern =~ m{%(\d+)} ) { $self->{residue_loop} = $1 if $self->{residue_loop}; if ( $flag eq 1) { my $res = $self->{before} % $1; $res = $self->_recursive_calc($res); $pattern = $self->_return_substituted('^\d+%\d+', $res); } else { my $res = $i % $1; $pattern =~ s{%\d+}{$res}; } $self->_calculate($pattern, $i, 0); } elsif ( $pattern =~ m{\+(\d+)} ) { if ( $flag eq 1) { my $res = $self->{before} + $1; $res = $self->_recursive_calc($res); $pattern = $self->_return_substituted('^\d+\+\d+', $res); } else { my $res = $i + $1; $pattern =~ s{\+\d+}{$res}; } $self->_calculate($pattern, $i, 0); } elsif ( $pattern =~ m{-(\d+)} ) { if ( $flag eq 1) { my $res = $self->{before} - $1; $res = $self->_recursive_calc($res); $pattern = $self->_return_substituted('^\d+-\d+', $res); } else { my $res = $i - $1; $pattern =~ s{-\d+}{$res}; } $self->_calculate($pattern, $i, 0); } else { delete $self->{pattern}, $self->{before}; $self->{residue_loop} = 1; return $pattern; } } sub _recursive_calc { my ($self, $res) = @_; if ( defined $self->{residue_loop} && $self->{residue_loop} > 1 && ($res < 0 || $res > $self->{residue_loop}) ) { $res += $self->{residue_loop}; } return $res; } sub _return_substituted { my ($self, $regexp, $res) = @_; $self->{pattern} =~ s{$regexp}{$res}; return $self->{pattern}; } sub _is_recursive_start { my $self = shift; my $pattern = shift; ( $pattern =~ /^\d+/ && $pattern !~ /^\d+$/ ) ? return 1 : return 0; } sub _set_debug { my $self = shift; $self->{debug} = 1; return $self; } 1; __END__ =head1 NAME Text::CSV::BulkData - generate csv file with bulk data =head1 SYNOPSIS use Text::CSV::BulkData; my $output_file_1 = "/your/dir/example.dat"; my $format_1 = "0907000%04d,JPN,160-%04d,type000%04d,0120444%04d,2008041810%02d00,2008041811%02d00\n"; my $pattern_1 = [undef,'*2*2','-2','*2+1','%60-1','%60-40']; my $gen = Text::CSV::BulkData->new($output_file_1, $format); my $pattern_1 = [undef,'*2','-2','*2+1']; $gen->initialize ->set_pattern($pattern_1) ->set_start(59) ->set_end(62) ->make; my $output_file_2 = "/your/dir/yetanotherfile.dat"; my $format_2 = "0907000%04d,JPN,160-%04d,type000%04d,0120444%04d,20080418%02d0000,20080419%02d0000\n"; my $pattern_2 = [undef,'/10','*3/2','%2', '%24-1','%24']; $gen->set_output_file($output_file_2) ->set_format($format_2) ->set_pattern($pattern_2) ->set_start(239) ->set_end(241) ->make; This sample generates following csv file. /your/dir/example.dat 09070000059,JPN,160-0236,type0000057,01204440119,20080418105800,20080418111900 09070000060,JPN,160-0240,type0000058,01204440121,20080418105900,20080418112000 09070000061,JPN,160-0244,type0000059,01204440123,20080418100000,20080418112100 09070000062,JPN,160-0248,type0000060,01204440125,20080418100100,20080418112200 /your/dir/yetanotherfile.dat 09070000239,JPN,160-0023,type0000358,01204440001,20080418220000,20080419230000 09070000240,JPN,160-0024,type0000360,01204440000,20080418230000,20080419000000 09070000241,JPN,160-0024,type0000361,01204440001,20080418000000,20080419010000 =head1 DESCRIPTION Text::CSV::BulkData is a Perl module which generates csv files with bulk data. You can modify incremented values with using addition(+), subtraction(-), multiplication(*), division(/) and residue(%). Precedence of operators is '*', '/', '%', '+', '-'. The right of the decimal point are truncated. =head1 SEE ALSO None =head1 AUTHOR Kazuhiro Sera, Ewebmaster@seratch.ath.cxE =head1 COPYRIGHT AND LICENSE Copyright (C) 2008 by Kazuhiro Sera This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available. =cut