Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Re: Processing CSV File

by Athanasius (Archbishop)
on Oct 03, 2012 at 06:11 UTC ( [id://996984]=note: print w/replies, xml ) Need Help??


in reply to Processing CSV File

Hello Perl3r, and welcome to the Monastery!

You are opening the output file $ofile_name each time through the outer while loop. This truncates the file each time before writing to it! Move the statement open(OFILE, ...) ... to before the first while loop, so that the file is opened only once.

Update 1: Sorry, I didn’t see that the name of the output file is changing on each pass of the outer loop.  :-(

It is also good practice to begin your scripts with

use strict;

and to declare lexical variables using my.

Hope that helps,

Update 2: I created two files:

(1) “data.csv”

here,fred,42,43,44,45 there,wilma,2,5,7,9

(2) “rtr-template.txt”

this is the ##location## to be in! my name is ##rtrname##. the frame is '##frame-DLCI##'.

Then I invoked your original script as:

perl test_script.pl data.csv

And the result was two output files:

(a) “fred.txt“

this is the here to be in! my name is fred. the frame is '44'.

(b) “wilma.txt”

this is the there to be in! my name is wilma. the frame is '7'.

— which is exactly as expected. So, I cannot reproduce the problem you are seeing. Are you sure you are running the code as described?

Athanasius <°(((><contra mundum

Replies are listed 'Best First'.
Re: Processing CSV File
by Perl3r (Novice) on Oct 03, 2012 at 06:40 UTC

    Thanks for the response.. I did the following;

    #!/usr/bin/perl # $template_file_name="rtr-template.txt"; open(OFILE, "> test") || die "output config file $ofile_name: $!\n"; while(<>) { ($location, $name, $lo0ip, $frameip, $framedlci, $eth0ip, $x) = split (/,/); open(TFILE, "< $template_file_name") || die "config template file $ +template_file_name: $!\n"; $ofile_name = $name . ".txt"; while (<TFILE>) { s/##location##/$location/; s/##rtrname##/$name/; s/##eth0-ip##/$eth0ip/; s/##loop0-ip##/$lo0ip/; s/##frame-ip##/$frameip/; s/##frame-DLCI##/$framedlci/; printf OFILE $_; } }

    I tried just moving the line as is, but since $ofile_name hadn't been defined yet, that would't work.. so i replaced the variable with 'Test' This creates a file called Test with the information required.. however still only processes the first line of the CSV - as i guess is expected, as it is emulating the same problem as before.. If i move the line "$ofile_name = $name . ".txt";" to the top aswell, so it looks like:

    #!/usr/bin/perl # $template_file_name="rtr-template.txt"; $ofile_name = $name . ".txt"; open(OFILE, "> test") || die "output config file $ofile_name: $!\n"; while(<>) { ($location, $name, $lo0ip, $frameip, $framedlci, $eth0ip, $x) = split (/,/); open(TFILE, "< $template_file_name") || die "config template file $ +template_file_name: $!\n"; while (<TFILE>) { s/##location##/$location/; s/##rtrname##/$name/; s/##eth0-ip##/$eth0ip/; s/##loop0-ip##/$lo0ip/; s/##frame-ip##/$frameip/; s/##frame-DLCI##/$framedlci/; printf OFILE $_; } }

    then when i run the code, I don't get any files outputted.. Do you have any ideas, what is going on... Thanks again

      If I may suggest considering a slightly different approach to your task...

      It appears that you're opening the template file each time a csv line is read, so that you can fill in the template with the entries. Consider opening the template file only once, and grabbing its contents into a scalar. Then, you can do the substitutions on a copy of that scalar, and write that copy to a file. Doing that may look something like this:

      #!/usr/bin/perl # use strict; use warnings; my ( $templateText, %hash ); my $template_file_name = 'rtr-template.txt'; my @vars = split "\n", <<END; ##location## ##rtrname## ##loop0-ip## ##frame-ip## ##frame-DLCI## ##eth0-ip## END { local $/; open my $fh, '<', $template_file_name or die "$template_file_name: + $!"; $templateText = <$fh>; close $fh; } while (<>) { chomp; @hash{@vars} = split /,/; my $templateTextCopy = $templateText; $templateTextCopy =~ s/$_/$hash{$_}/g for keys %hash; my $ofile_name = $hash{'##rtrname##'} . '.txt'; open my $fh, '>', $ofile_name or die "$ofile_name: $!"; print $fh $templateTextCopy; close $fh; }

      You'll notice this notation: @hash{@vars} = split /,/; It pairs the elements of @var as keys with the split entries of the csv line as values of %hash. This creates the hash that's used in the substitution line, taking the place of the six substitution lines. Also, note that the substitution is global, because your script was going through all the lines of the template for the substitutions.

      Hope this helps!

        Thanks, This is a great version of the code.. One question for you.. How would I change the "my $template_file_name = 'rtr-template.txt'" line to chose a template that is specified in the CSV.. rather than a file saved on the HDD.. So if I just added another column to the CSV.. this would make the script a bit more dynamic for different templates.. Thanks!

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (7)
As of 2024-04-23 07:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found