Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Esteemed monks

I am a new perl programmer and struggle with the language and its idioms (but I'm trying!). I need to add a new column to an existing CSV file. It needs to be the second column in the file but it could be the first or last if that is easier. I was recommended to look at http://search.cpan.org/~jwied/Text-CSV_XS-0.23/CSV_XS.pm. I have looked but I can only see how to create new CSVs rather than modify existing ones. Please could you point me in the right direction and give me an outline of how to do this. I'm not asking anyone to do it for me but I am hoping some pointers from you experts will spend me hours of banging my head against the wall.

Many thanks for your time

Replies are listed 'Best First'.
Re: adding a new column to a CSV
by wind (Priest) on Apr 23, 2011 at 01:45 UTC
    Adapted straight from the example in Text::CSV:
    use File::Copy qw(move); use Text::CSV; use strict; use warnings; my $csv = Text::CSV->new({binary => 1, eol => "\n"}) or die "Cannot use CSV: ".Text::CSV->error_diag (); my $oldfile = 'old.csv'; my $newfile = $oldfile . '.tmp'; open my $in, $oldfile or die "$oldfile: $!"; open my $out, '>', $newfile or die "$newfile: $!"; while (my $row = $csv->getline($in)) { splice @$row, 1, 0, "New Col 2"; $csv->print($out, $row); } close $in; close $out; move($newfile, $oldfile) or die "Can't move: $!";
Re: adding a new column to a CSV
by Tux (Canon) on Apr 23, 2011 at 07:07 UTC

    I don't know who gave you that advice, but version 0.23 is almost 10 years old and full of bugs (by modern standards). If you want to study the current state of CSV parsing, you should look at Text::CSV_XS and Text::CSV. Both have other maintainers than 10 years ago, and both do now mostly what the community expects it to do and more. The XS version is way faster than the pure-perl version, but it is save to always use Text::CSV, as that will use Text::CSV_XS under the hood if it is installed.

    wind's paste is fine. I would make small changes to include the relative new auto_diag to catch all errors:

    use File::Copy qw(move); use Text::CSV; use strict; use warnings; use autodie; # no need to catch open/read/write/close errors anymore my $csv = Text::CSV->new ({ binary => 1, auto_diag => 1, eol => "\n" } +); my $oldfile = "old.csv"; my $newfile = $oldfile . ".tmp"; open my $in, "<", $oldfile; open my $out, ">", $newfile; while (my $row = $csv->getline ($in)) { splice @$row, 1, 0, "New Col 2"; $csv->print ($out, $row); } close $in; close $out;

    Enjoy, Have FUN! H.Merijn
      I am having a bit of trouble with this because it seems to be putting quotes around some of the column values. Using an example tab limited file with 4 lines, the final column on every row apart from the last one is put in quotes

      Also using this code

      splice @$row, 1, 0, "New Col 2";
      the new column text is in quotes which I don't want.

      thank-you

        You obviously did not take the time to read the exhaustive documentation the comes with Text::CSV_XS. By default, fields with spaces are quoted. There is an option (attribute) available to do the opposite:

        quote_space By default, a space in a field would trigger quotation. As +no rule exists this to be forced in CSV, nor any for the opposite, +the default is true for safety. You can exclude the space from +this trigger by setting this attribute to 0.

        Enjoy, Have FUN! H.Merijn
Re: adding a new column to a CSV
by Anonymous Monk on Apr 23, 2011 at 01:29 UTC
    I have looked but I can only see how to create new CSVs rather than modify existing ones.

    Good, because modifying an existing one is simply

    1. create a new one
    2. rename new one to name of old one