Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Question about parsing columns when using Text::CSV

by amdevious (Initiate)
on Jan 06, 2009 at 15:06 UTC ( [id://734453]=perlquestion: print w/replies, xml ) Need Help??

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

Hi all. I'm new to this site and also to Perl. Was wondering if I could get some guidance.

I have a csv file in the following format:
25.484000,23.327000,.000000,27.026000,26.616000,28.414000,21.704000 47.292000,27.944000,18.266000,18.702000,4.384000,26.765000,43.507000 21.773000,28.077000,.000000,25.974000,30.354000,17.996000,7.765000 25.484000,23.327000,.000000,27.026000,26.616000,28.414000,21.704000 47.292000,27.944000,18.266000,18.702000,4.384000,26.765000,43.507000 21.773000,28.077000,.000000,25.974000,30.354000,17.996000,7.765000
I need to parse out the data to only 3 decimal places.

I have the following code to work on the CSV file but cant get my print statements correct to truncate the numbers.

#!/usr/bin/perl use strict; use warnings; use Text::CSV; my $file = '112008.csv'; my $output='112008.txt'; my $csv = Text::CSV->new(); open (CSV, "<", $file) or die $!; open(OUTFILE,">$output") || die "Can't open file $output"; while (<CSV>) { if ($csv->parse($_)) { my @columns = $csv->fields(); printf OUTFILE "@columns\n"; } else { my $err = $csv->error_input; print "Failed to parse line: $err"; } } close CSV;
Any help would be appreciated.

Replies are listed 'Best First'.
Re: Question about parsing columns when using Text::CSV
by kennethk (Abbot) on Jan 06, 2009 at 15:14 UTC

    Code tags are your friends: see Markup in the Monastery.

    Try using sprintf to format your output (e.g. sprintf "%.3f"). That will generate a formatted string you can feed to a print statement.

      An example of how to parse a csv (comma separated values) file is at http://www.biterscripting.com/Download/SS_CSV.txt . I have been using it. Seems good. Their scripts are open source and free at http://biterscripting.com . Don't even have to provide an email.
Re: Question about parsing columns when using Text::CSV
by borisz (Canon) on Jan 06, 2009 at 15:15 UTC
    Use sprintf to truncate the numbers.
    my @columns = map { sprintf("%.3f", $_) } $csv->fields();
    should work. untested
    Boris
Re: Question about parsing columns when using Text::CSV
by Tux (Canon) on Jan 06, 2009 at 15:40 UTC

    In order to start programming defensive and safe, don't use the diamond for CSV

    use strict; use warnings; use Text::CSV; my ($file, output) = ("112008.csv", "112008.txt"); my $csv = Text::CSV->new ({ binary => 1 }); open my $ih, "<", $file or die "Can't open in file $file: $!"; open my $oh, ">", $output or die "Can't open out file $output: $!"; while (my $row = $csv->getline ($ih)) { my @columns = map { sprintf "%.3f", $_ } @$row; # do something with @columns print { $oh } join "|", @columns, "\n"; } $csv->eof () or $csv->error_diag (); close $ih or die "$file: $!"; close $oh or die "$output: $!";

    Enjoy, Have FUN! H.Merijn

      Greetings. What exactly is wrong with using the diamond operator here? What specifically makes it unsafe, and why is using your method considered "better defense?" Thanks.

      jeffa

      L-LL-L--L-LL-L--L-LL-L--
      -R--R-RR-R--R-RR-R--R-RR
      B--B--B--B--B--B--B--B--
      H---H---H---H---H---H---
      (the triplet paradiddle with high-hat)
      

        Short answer: nested newlines

        Longer answer: Though in the case of the OP, there are no embedded newlines or other binary characters, it's just waiting for it to happen one day or another when new fields are added to the end. CSV is safe and defined enough to cope, but if the diamond is used to read CSV (in general), all lines that have embedded newlines will cause the CSV parsing to fail from that point on.

        Note that the $csv->getline () will use the diamond (CORE's getline ()) internally too, but Text::CSV (and Text::CSV_XS and Text::CSV_PP) will know internally that the line might not be finished and will correct that on a need-to-be basis.

        Another reason to use getline () instead of diamond, is that the getline () is magnitudes faster than the combination of diamond + parse (), even when using Text::CSV_PP.


        Enjoy, Have FUN! H.Merijn
Re: Question about parsing columns when using Text::CSV
by fullermd (Priest) on Jan 06, 2009 at 15:18 UTC

    The first bit of help is to see Markup in the Monastery and use <code> tags so the code is readable. Like:

    #!/usr/bin/perl use strict; use warnings; use Text::CSV; my $file = '112008.csv'; my $output='112008.txt'; my $csv = Text::CSV->new(); open (CSV, "<", $file) or die $!; open(OUTFILE,">$output") || die "Can't open file $output"; while (<CSV>) { if ($csv->parse($_)) { my @columns = $csv->fields(); printf OUTFILE "@columns\n"; } else { my $err = $csv->error_input; print "Failed to parse line: $err"; } } close CSV;

    Lot easier to read and comment on then.

Re: Question about parsing columns when using Text::CSV
by eighty-one (Curate) on Jan 06, 2009 at 16:05 UTC

    I find formats to be very handy in some situations.

    And here's an article with some more information on them.

    Basically, you can define fields with set widths and fixed characters, and your variables are displayed as indicated by the format you define. Depending on what you plan to do with your output, this might be useful.

    It will track pages if you define the number of lines per page and define page headers, but you can set the settings so that no headers will be printed.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://734453]
Approved by ikegami
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (5)
As of 2024-03-28 22:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found