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

Hi, I am working on changing a column output from from a command to a horzontal delimited line for loading into a DB. Thought it would be simple, but my mind is making it very complex and ugly, so I am seeking wisdom on a cleaner method. Sample imput is this.
Update Time: 2005.04.27 15:44:12 Targets: 4 Complete: 4(100%) Waiting: 0
Output should look like this
Update Time,Targets,Complete,Waiting 2005.04.27 15:44:12,4,4(100%),0
I had created a hash by splitting on the : and pushing the keys and values into seperate arrays and then printing the arrays back. But the time value HH:MM:SS causes problems and I don't like assuming that the headers will match the values by printing the array of keys then the array of values. Sample
while(my($key, $value) = each(%list)){ push(@headers, $key); push(@values, $value); } print "@headers\n"; print "@values\n";

Replies are listed 'Best First'.
Re: Creating a CSV file
by dragonchild (Archbishop) on Apr 28, 2005 at 19:00 UTC
Re: Creating a CSV file
by JediWizard (Deacon) on Apr 28, 2005 at 18:59 UTC

    I would look at Text::CSV


    They say that time changes things, but you actually have to change them yourself.

    —Andy Warhol

Re: Creating a CSV file
by Transient (Hermit) on Apr 28, 2005 at 18:51 UTC
    I believe there is a module out there that does this (I'm sure someone will post what it is), but in the meantime:

    1. add a third option to split in order to limit the number of results (e.g. split( ':', $_, 2 ) will return two elements based upon the first encountered ":")
    2. The headers and values will match, by definition.

    However, this doesn't work well for multiple values of your headers (e.g. multiple Update Times, etc.) as you'll only get the last value.
Re: Creating a CSV file
by trammell (Priest) on Apr 28, 2005 at 21:00 UTC
    But the time value HH:MM:SS causes problems...

    How? If this is a CSV file, you only need to worry about commas and quotation marks.
    Update: I see--you're having issues parsing the date from your input lines. I was assuming the title of your post referred to this problem...

    and I don't like assuming that the headers will match the values by printing the array of keys then the array of values.

    One solution to this problem is to use a hash slice:

    my @keys = ("Update Time", qw/Targets Complete Waiting/); my %hash; # fill in %hash (method not clear from OP) print join ',', @hash{ @keys }; # or use e.g. Text::CSV_XS
Re: Creating a CSV file
by LanceDeeply (Chaplain) on Apr 28, 2005 at 20:08 UTC
    you could split on colon space and then use map to ensure the order of your values matches the order of your keys... but, as Transient stated, your order is already ok
    my %hash; while ( <DATA> ) { chomp; my @ar = split /\: /,$_; $hash{$ar[0]} = $ar[1]; } my @keys = keys %hash; my @values = map { $hash{$_} } @keys; print join ",",@keys; print "\n"; print join ",",@values; print "\n"; __DATA__ Update Time: 2005.04.27 15:44:12 Targets: 4 Complete: 4(100%) Waiting: 0

    Waiting,Targets,Update Time,Complete 0,4,2005.04.27 15:44:12,4(100%)
Re: Creating a CSV file
by NateTut (Deacon) on Apr 28, 2005 at 20:41 UTC
    I would do this by making an array of hashes. Your "headers" would become the keys of the hashes. Then push them on an array when you are done. Like this:
    use strict; use warnings; use Data::Dumper; my @Values; my $HashSet = (); while(<DATA>) { chomp(); (my $Header, my $Value) = split /: /, $_, 2; $HashSet->{$Header} = $Value; if($Header eq 'Waiting') { push(@Values, $HashSet); $HashSet = (); } } print(Dumper(@Values)); __DATA__ Update Time: 2005.04.27 15:44:12 Targets: 4 Complete: 4(100%) Waiting: 0 Update Time: 2005.04.27 15:45:10 Targets: 10 Complete: 5(50%) Waiting: 5 Update Time: 2005.04.26 12:15:08 Targets: 3 Complete: 1(33%) Waiting: 2