http://qs1969.pair.com?node_id=1227312


in reply to Re^4: Read CSV with column mapping
in thread Read CSV with column mapping

scalar(@$colref) is the number of items found in the column, it would never contain a '#' symbol.

$colref->[0] is the first item on the line read in, it could contain a # symbol.

if ($colref->[0] =~ /^#/) { next; }

Notice i said next rather than last. next will go on to the next row, last will end the do loop and stop reading any more lines.

the next condition is a touch more tricky.

my $anynonblank=0; for my $item (@$colref){ unless ($item =~ /^\s+$/) { $anynonblank=1; last; } } unless ($anynonblank) { next; }
See we have to test all of the items in this case. Note th use of last here, as soon as we have found any nonblank we dont have to check anymore.

edit: opps , fixed as per Re^6: Read CSV with column mapping below

Replies are listed 'Best First'.
Re^6: Read CSV with column mapping
by AnomalousMonk (Archbishop) on Dec 16, 2018 at 06:31 UTC
    unless ($item =~ /^s+$/) { ... }

    The  $item =~ /^s+$/ expression matches against a  's' literal character and not, as I think was intended, the  \s whitespace character class.


    Give a man a fish:  <%-{-{-{-<

Re^6: Read CSV with column mapping
by coretele (Novice) on Dec 16, 2018 at 17:59 UTC

    I have tried your suggestion and it did help to avoid comments but not for blank lines. Here I am provide the code and config file. Also providing output.

    use strict; use warnings; use Data::Dumper; use Text::CSV_XS; use IO::File; my $hash_ref = csv_file_hashref('parameters.conf'); foreach my $key (sort keys %{$hash_ref}){ print qq{$key:}; print join q{,}, @{$hash_ref->{$key}}; print qq{\n}; } sub csv_file_hashref { my ($filename) = @_; my $csv_fh = IO::File->new($filename, 'r'); my $csv = Text::CSV_XS->new (); my %output_hash; while(my $colref = $csv->getline ($csv_fh)) { if ($colref->[0] =~ /^#/) { next; } my $anynonblank=0; for my $item (@$colref){ unless ($item =~ /^\s+$/) { $anynonblank=1; last; } } unless ($anynonblank) { next; } #print @$colref; #print "\n"; $output_hash{shift @{$colref}} = $colref; } return \%output_hash; } 1;
    config file-
    #sdadwlasda abc xyz,10 #ldfgld xyz pqr,2 #jwej pqr stq,0.1 # # # #
    Output-
    : abc xyz:10 pqr stq:0.1 xyz pqr:2

      Two alternatives:

      use 5.14.1; use warnings; use Data::Peek; use Text::CSV_XS "csv"; my %hash; csv (in => "pm1227312.csv", out => undef, on_in => sub { my ($key, $value) = @{$_[1]}; $key && $key !~ m/^\s*(?:#|$)/ and $hash{$key} = $value; }); DDumper \%hash; %hash = map { @$_ } @{csv (in => "pm1227312.csv", filter => { 0 => sub + { !m/^\s*(?:#|$)/ }})}; DDumper \%hash;

      Enjoy, Have FUN! H.Merijn
        At least read the documentation for Text::CSV. Even if you do not use the module, its discussion of special cases should be useful. Please ignore this post. I am not sure how I replied to such an old thread.
        Bill

      You could just check if the key is blank

      #!/usr/bin/perl use strict; use warnings; use Data::Dumper; use Text::CSV_XS; use IO::File; my $hash_ref = csv_file_hashref('parameters.conf'); foreach my $key (sort keys %$hash_ref){ print $key.':'; print join ',', @{$hash_ref->{$key}}; print "\n"; } sub csv_file_hashref { my ($filename) = @_; my %output_hash = (); my $csv_fh = IO::File->new($filename, 'r'); my $csv = Text::CSV_XS->new( { allow_whitespace => 1 } ); while (my $row = $csv->getline($csv_fh)){ my $key = shift @$row; next if $key =~ /^#/; if ($key =~ /\S/){ $output_hash{$key} = $row ; } } return \%output_hash; }

      Note $item =~ /^\s+$/ matches 1 or more white space only (but not nothing). Try $item =~ /^\s*$/ in your code.

      poj
        Thanks. This worked for me now. On the side note. How can I implement object oriented concept (encapsulation) in this same scenario? e.g. if I want to do following. A.pm
        -> sub Initialize read config file and construct hash and return self object sub get_value(string parameter, string key) return value
        config file:
        parameter, key, value, id abc, xyz, 1, 100 blue, pqr, 0.1, 101
        Thanks.

      /^\s+$/ requires at least one blank character. /^\s*$/ would fail empty lines too.