-1

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;
Borodin
  • 126,100
  • 9
  • 70
  • 144
DKru
  • 19
  • 3
  • 2
    Take the output of `split` to an array and then do any operation on columns. – AbhiNickz Jun 28 '17 at 13:35
  • 3
    As far as I can tell, you want to change your CSV file to have a fixed width of ten characters per field. *"At this stage, I hash and unhash the columns that need to be edited, but its tedious"* I don't understand that, and there's no evidence of "hashing" anything in your code. Please can you explain what is wrong with what you've written and exactly what your question is? If it's simply that you're using a separate scalar variable for each column then surely the answer is to use an array? – Borodin Jun 28 '17 at 14:03

2 Answers2

3

Do you mean something like this?

perl -aF/,/ -lne 'print map sprintf("%10s", $_), @F' FILENAME.csv > FILENAME.txt
Borodin
  • 126,100
  • 9
  • 70
  • 144
  • Thank you!! Seeing an answer like this just depresses me.. all that coding and could have been simplified into one line - I have much too learn!! – DKru Jun 28 '17 at 15:30
  • @DKru: The most important lesson is to use an *array* instead of multiple scalar variables. That shrinks your own code by about 80%. – Borodin Jun 28 '17 at 21:48
-1

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;
Sobrique
  • 52,974
  • 7
  • 60
  • 101