Search code examples
perlcsvmultiple-columnsfixed-width

Make the same edit for edit for each column in a multi-column file


I have multiple CSV files with varying numbers of columns that I need to reformat into a fixed-format text file.

At this stage, I hash and unhash the columns that need to be edited, but its tedious and I can't add new columns without changing the program first.

Is there a simpler way of reading, splitting and editing all columns, regardless of the number of columns in the file?

Here is my code thus far:

use strict;
use warnings;

my $input = 'FILENAME.csv';
my $output = 'FILENAME.txt';

open (INPUT, "<", "$input_file") or die "\n !! Cannot open $input_file: $!";
open (OUTPUT, ">>", "$output_file") or die "\n !! Cannot create $output_file: $!";

while ( <INPUT> ) {

    my $line = $_;
    $line =~ s/\s*$//g;

    my ( $a, $b, $c, $d, $e, $f, $g, $h, $i, $j ) = split('\,', $line);

    $a = sprintf '%10s', $a;
    $b = sprintf '%10s', $b;
    $c = sprintf '%10s', $c;
    $d = sprintf '%10s', $d;
    $e = sprintf '%10s', $e;
    $f = sprintf '%10s', $f;
    $g = sprintf '%10s', $g;
    $h = sprintf '%10s', $h;
    $i = sprintf '%10s', $i;
    $j = sprintf '%10s', $j;

    print OUTPUT "$a$b$c$d$e$f$g$h$i$j\n";

}

close INPUT;
close OUTPUT;

exit;

Solution

  • Any time you're using sequential variables, you should be using an array. And in this case, since you only use the array once, you don't even need to do more than hold it temporarily.

    Also: Use lexical filehandles, it's better practice.

    #!/usr/bin/env perl
    
    use strict;
    use warnings;
    
    my $input_file  = 'FILENAME.csv';
    my $output_file = 'FILENAME.txt';
    
    my $format = '%10s';
    
    open( my $input_fh, "<", $input_file ) or die "\n !! Cannot open $input_file: $!";
    open( my $output_fh, ">>", $output_file ) or die "\n !! Cannot create $output_file: $!";
    
    while (<$input_fh>) {
       print {$output_fh} join "", map { sprintf $format, $_ } split /,/;
    }
    
    close $input_fh;
    close $output_fh;
    
    exit;