Given a CSV file like this:

examples/plain.csv

a,b,c
d,e,f
g,h,i

How can you convert it to a file like this:

examples/flattened.csv

a
b
c
d
e
f
g
h
i

Solution with split

Using split is not going to work for every CSV file,but for simple ones, like the input file on our example it can work as well.

examples/flatten_csv.pl

use strict;
use warnings;

my ($infile, $outfile) = @ARGV;
die "Usage: $0 INFILE OUTFILE\n" if not $outfile;

open my $in, '<', $infile or die;
my @entries;
while (my $line = <$in>) {
    chomp $line;
    push @entries, split /,/, $line;
}
close $in;

open my $out, '>', $outfile or die;
for my $entry (@entries) {
    print $out "$entry\n";
}
close $out;

Run it this way:

perl examples/flatten_csv.pl examples/plain.csv examples/flattened.csv

Solution using Text::CSV

The more generic solution using Text::CSV:

examples/flatten_text_csv.pl

use strict;
use warnings;
use Text::CSV;

my ($infile, $outfile) = @ARGV;
die "Usage: $0 INFILE OUTFILE\n" if not $outfile;

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

open my $in, '<:encoding(utf8)', $infile or die;
my @entries;
while (my $fields = $csv->getline( $in )) {
  push @entries, @$fields;
}
close $in;

open my $out, '>', $outfile or die;
for my $entry (@entries) {
    print $out "$entry\n";
}
close $out;

Comments

sub slurp { local (@ARGV,$/)=shift; readline; }

my @_a=slurp($ARGV[0]) =~ m{([^,\n]+)[,\n](?{print "$1\n"})}g;