Home > Enterprise >  Perl script to print all the column from a csv file into rows in a new file
Perl script to print all the column from a csv file into rows in a new file

Time:01-24

my .csv file looks like:

sim_time,a,b,c,d
0,0,0,0,0
12,0,1,1,0
115,1,1,1,1
200,0,0,1,0

I have multiple csv file in which no of rows and column are different .

The output should look like :

sim_time 0 12 115 200
a 0 0 1 0
b 0 1 1 0
c 0 1 1 1
d 0 0 1 0

The code i am trying to use is as follows:

#!/usr/bin/perl
my $file = "report_69.csv";
my $column_separator = ',';
open (my $INFILE, "<" , "$file");
open(my $FILE,">","report_69.txt") or die "$!";
while (<$INFILE>) {
    chomp;
    my @c = split(',', $_);
    my $d = @c;
    print $d;
    my @columns = split(/$column_separator/);

    for( $a = 0; $a < $d; $a = $a   1 ) {
        push ("@x_{$a}", $columns[$a] );    # the problem (1) 
    }
}

The problem (1) arise while defining the array as it is not a valid way to define the array. Is there any other way to do the same.

Now I am facing issue while content of the each column into an array because I can define the multiple array as per need .

CodePudding user response:

The data in the CSV file need be transposed, judged by the shown desired output

use warnings;
use strict;
use feature 'say';

use Text::CSV;

my $file = shift // die "Usage: $0 file\n";

my $csv = Text::CSV->new ({ binary => 1, auto_diag => 2 });

my @data;
open my $fh, $file or die "Can't open $file: $!";    
while ( my $row = $csv->getline($fh) ) { 
    push @data, $row;
}
close $fh;

# Transpose data
my @res;
foreach my $row (@data) {
    foreach my $col_n (0 .. $#$row) {
        push @{ $res[$col_n] }, $row->[$col_n];
    }
}

# Print results
for my $row (@res) {
    say "@$row";
}

The syntax $#$name stands for the last index in an array reference of that name.

While the shown data is easily parsed by hand it is always better to entrust the job to a library for CSV and I use the excellent Text::CSV to read the CSV file.

The resulting (transposed) data is printed to STDOUT and so can be redirected to a file. Or change the last part to print directly to a file.


NOTE   The shown input has a missing field in the fourth row (115,1,1,1) but the shown desired output doesn't, effectively showing a 1 for it. I am ignoring this until clarified, considering it as a typo in posting.


Even as just

my @data = map { chomp; [ split /\s*,\s*/ ] } <>;

for a file with the name given on the command line (so found in @ARGV and thus read line by line by <>). However, as soon as there is anything more interesting in the file -- spaces, newlines, quotes, ... -- we really want a library. So just use a library.

CodePudding user response:

My simplistic answer:

#!/usr/bin/perl
use warnings; use strict;

my $file = "data.txt";
my $column_separator = ',';
open (my $INFILE, "<" , "$file");

my @rows = ();

my $row=0;
while (<$INFILE>) {

  chomp;
  next if (/^$/);

  my @cols = split(",");

  for(my $c = 0; $c < scalar @cols; $c  ) {
    $rows[$c][$row] = "" . $cols[$c];
  }

  $row  ;
}

for my $row(@rows) {
  print join(",", @{$row}), "\n";
}

I'm no perl expert, but this seems to tick the box (file handling excepted).

  • Related