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

Hey

I have started working on csv file , and I want only a particular column of a csv file (column as in when seen with excel ) . I don't wish to split it by a delimiter because there can be special characters as part of csv file as well . is there any method to do it , I have seen csv::text cpan , but it does not talk about extraction of any column as individual

Replies are listed 'Best First'.
Re: Extract a column of csv
by kcott (Archbishop) on Jun 26, 2013 at 04:15 UTC
    "I have seen csv::text cpan , but it does not talk about extraction of any column as individual"

    Yes it does! You couldn't have read very far: it's in the first few lines of Text::CSV SYNOPSIS:

    $row->[2] ... # 3rd field ...

    -- Ken

Re: Extract a column of csv
by kevbot (Vicar) on Jun 26, 2013 at 04:52 UTC
    You may want to take a look the Data::Table cpan module. It has a fromCSV method to create a Data::Table object from a csv file. Then, a specific column can be obtained with the subTable method. For example,
    use Data::Table; my $t = Data::Table::fromCSV("aaa.csv"); my $c = $t->subTable(undef, ['MyColumnHeader']); my $column_data_ref = $c->data;
Re: Extract a column of csv
by Loops (Curate) on Jun 26, 2013 at 04:32 UTC

    And just to prove it ;o)

    use strict; use warnings; use utf8; use Text::CSV; my $io = \*DATA; my $csv = Text::CSV->new ({ binary => 1 }); while (my $row = $csv->getline($io)) { print $row->[1], "\n"; } __DATA__ 33,44,55,"ABC" 234.33,"ABC ""DEFGHIJ"" KLMNOP","asdfasd asdfasdfasdf "
    Produces:
    44 ABC "DEFGHIJ" KLMNOP
      Hey

      what if I define it as any sub routine that extracts a particular column so that i can return the extracted array

      Hey

      thank you for helping out , I have just one question that here in line

       print $row->[1], "\n";

      our 1 is fixed but i want to extract multiple columns , so I wrote a subroutine

      sub column_segregation { my $o=$_[0]; print "$o \n"; my @array_A2=(); my $csv = Text::CSV->new ({ binary => 1 }); while (my $row = $csv->getline($io)) { push @array_A2, $row->[$o]; } return (@array_A2); }

      but here $o is changing but it constantly returns the same array , which is at location 2. can you please tell me what is wrong in my code

Re: Extract a column of csv
by Tux (Canon) on Jun 26, 2013 at 05:57 UTC
    # get the 4th column my @column = map { $_->[3] } @{$csv->getline_all ($fh)};

    Enjoy, Have FUN! H.Merijn
      hey i did this as per your advice
      my $in_file = 'C:\Documents and Settings\x0199665\My Documents\coll\t +gb.csv'; # open my $fh, '<', $in_file or die "could not open $in_file: $!\n"; my @column = map { $_->[4] } @{$csv->getline_all ($fh)};
      but it gives an error "can't call getline on an unidentified value

        Please start reading the documentation for Text::CSV_XS or Text::CSV. To me this error indicates that you forgot to initiate the $csv object (or that you are using a very old Text::CSV):

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

        update: can I see both the script and the data? Not much has changed for getline_all () in Text::CSV_XS since Dec 2010, when it was introduced


        Enjoy, Have FUN! H.Merijn
Re: Extract a column of csv
by dasgar (Priest) on Jun 26, 2013 at 04:12 UTC

    On one hand, Text::CSV doesn't provide a built-in function to pull out just one specific column from a CSV file. On the other hand, you can use that module to do just that. In fact, I've written code to do something like that for use at work. The basic concepts are to parse the CSV one line at a time within a loop and then pull the desired column to store/print/etc.

Re: Extract a column of csv
by 2teez (Vicar) on Jun 26, 2013 at 04:12 UTC

    I have seen csv::text cpan , but it does not talk about extraction of any column as individual
    You mean Text::CSV?
    And how are you parsing your csv file?

    If you tell me, I'll forget.
    If you show me, I'll remember.
    if you involve me, I'll understand.
    --- Author unknown to me
Re: Extract Column of CSV - pretend its a database.
by space_monk (Chaplain) on Jun 26, 2013 at 08:44 UTC

    This is an alternative method to the Text::CSV techniques suggested above.

    If you're familiar with databases, you can use DBD::CSV to query the CSV file as a database and select the fourth column of data.

    If you spot any bugs in my solutions, it's because I've deliberately left them in as an exercise for the reader! :-)

      Why pretend? Assuming these two csv lines:

      11,22,33,"ABC" 1111,3333,4444,"asdfasd asdfasdfasdf"

      And assuming you have the file_fdw extension installed ( create extension file_fdw; ), you could have Pg query it via:

      create server pgcsv foreign data wrapper file_fdw; create foreign table pgcsv ( col1 int, col2 int, col3 int, col4 text ) server pgcsv options ( filename '/tmp/pm-1040691.csv', format 'csv' ); select * from pgcsv; -- or a single column, of course...

      which will output:

      CREATE SERVER CREATE FOREIGN TABLE col1 | col2 | col3 | col4 ------+------+------+---------------------- 11 | 22 | 33 | ABC 1111 | 3333 | 4444 | asdfasd asdfasdfasdf

      Obviously not the easiest way to go about it (and on top of that, postgres is rather picky about the text's precise format). I'm just showing this because you brought up "database" ;)

        Well thats one idea. I presume though you'd need the psql client installed on your PC. Your answer is ingenious but not Perl :-)

        If you spot any bugs in my solutions, it's because I've deliberately left them in as an exercise for the reader! :-)