CSV-Processor
view release on metacpan or search on metacpan
bin/csvjoin view on Meta::CPAN
for my $i ( 0 .. $#new_files ) {
my $lines_ref = read_file( $new_files[$i], array_ref => 1 );
my $header = shift @$lines_ref;
append_file( $buffer_file, [$header] ) if ( $i eq 0 );
append_file( $buffer_file, @$lines_ref );
unlink $new_files[$i];
}
my $csv = Text::AutoCSV->new( in_file => $buffer_file );
$csv->read();
my $nb_rows = $csv->get_nb_rows();
my @cols = $csv->get_fields_names();
my @ids = $csv->get_values( $opts{unique_column} );
@ids = uniq @ids;
# say "Found unique ids:\n".join( "\n", @ids ) if $opts{verbose};
my @data_in_new_csv;
my $repeated_records = 0;
for my $id (@ids) {
my $found_ar = $csv->search( $opts{unique_column}, $id );
my $row_hr = $csv->get_row_hr( $found_ar->[0] );
if ( scalar @$found_ar > 1 ) {
say "Duplicate found : " . $opts{unique_column} . " : " . $id
if $opts{verbose};
$repeated_records++;
my @a;
for my $row_number (@$found_ar) {
push @a, $csv->get_cell( $row_number, $opts{join_column} );
}
$row_hr->{ $opts{join_column} } = join( ',', @a )
}
push @data_in_new_csv, $row_hr;
}
unlink $buffer_file;
$csv = Text::CSV->new() or die "Cannot use CSV: " . Text::CSV->error_diag();
$csv->eol("\012");
$csv->sep_char(";");
open my $fh, ">:encoding(utf8)", $opts{out_file} or die "$opts{out_file}: $!";
$csv->column_names(@cols);
$csv->print_hr( $fh, $_ ) for @data_in_new_csv;
close $fh or die "$opts{out_file}: $!";
say "Total records in : " . $nb_rows if $opts{verbose};
say "Total records out : " . scalar @data_in_new_csv if $opts{verbose};
say "Repeated records : " . $repeated_records if $opts{verbose};
my $duplicates = $nb_rows - scalar @data_in_new_csv;
say "Total duplicates : " . $duplicates if $opts{verbose};
my $percentage = ( $duplicates / $nb_rows ) * 100;
printf( "CSV reduce percentage : %.2f \n", $percentage ) if $opts{verbose};
# Text::AutoCSV: error: illegal call while read is in progress, would lead to infinite recursion
# $csv->set_walker_hr(sub {
# my $hr = shift;
# my $found_ar = $csv->search( $opts{unique_column}, $hr->{ $opts{unique_column} } );
# my $row_hr = $csv->get_row_hr( $found_ar->[0] );
#
# if ( scalar @$found_ar > 1 ) {
# my @a;
# for my $row_number ( @$found_ar ) {
# push @a, $csv->get_cell($row_number, $opts{unique_column});
# }
# $row_hr->{ $opts{join_column} } = join ( ',' , @a)
# }
#
# return $hr;
# });
exit 0;
__END__
=pod
=encoding UTF-8
=head1 NAME
csvjoin - join all csv files in folder into one and remove duplicates
=head1 VERSION
version 1.01
=head1 SYNOPSIS
csvjoin -d </user/pavel/csv> -i <in_column_name_or_index> -o <column name to store source> -v
<in_column_name_or_index> could be column name if csv has header or just row number.
In case of using row number please make sure that csv column structure is same
Read csv files without subdirectories
All available options:
-d | --dir name of directory to process. by default is cwd
-i | --in number or name of column, data from which will be checked for unique, by default is id or first column
-j | --join number or name of column where data is different and where it is needed to join values
-f | --file name of output file, by default is unique.csv
-v | --verbose verbose mode
Examples of usage:
csvjoin
csvjoin -i 2
csvjoin ---in ID -v
=head1 DESCRIPTION
( run in 0.679 second using v1.01-cache-2.11-cpan-39bf76dae61 )