Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

running multiple loops

by ddrew78 (Sexton)
on Jun 01, 2012 at 14:38 UTC ( #973787=perlquestion: print w/ replies, xml ) Need Help??
ddrew78 has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,

I have a very confusing issue. What I have is a file with anywhere from 1-7 lines in it. What I need to do is print several lines to a new file based on each line in that file. Further, the contents of the new file need to be based on input from another file, and I need that second file to be processed completely for every line in the first file. Hope this makes sense. Below is the code I currently have. It works fine for the first line in file1, but not for subsequent lines.

File1
4546 4748
File2
IT IT IT IT IT IT IT
File3
918 908

What i need to get is output below:

File 918
SR-IT-SD4546-IBV-sw918-A SR-IT-SD4546-IBV-sw918-B SR-IT-SD4748-IBV-sw918-A SR-IT-SD4748-IBV-sw918-B
File 908
SR-IT-SD4546-IBV-sw908-A SR-IT-SD4546-IBV-sw908-B SR-IT-SD4748-IBV-sw908-A SR-IT-SD4748-IBV-sw908-B
The code I am trying to use is this:
open(MYINPUTFILE, "File1"); open(MYINPUTFILE1, "File2"); open(MYINPUTFILE2, "File3"); open(HOST, ">host"); open(HOST1, ">host1"); while (<MYINPUTFILE>) { my($line) = $_; chomp($line); for ($numsw = $swnum; $numsw > 0 ; $numsw-- ){ my $line1 = <MYINPUTFILE1>; chomp($line1); my $line2 = <MYINPUTFILE2>; chomp($line2); print HOST "SR-$line1-SD$line-IBV-sw$line2-A\n"; print HOST1 "SR-$line1-SD$line-IBV-sw$line2-B\n"; open (OUTHANDLE, ">>$line2"); print OUTHANDLE "SR-$line1-SD$line-IBV-sw$line2-A\n"; print OUTHANDLE "SR-$line1-SD$line-IBV-sw$line2-B\n"; close (OUTHANDLE"); } } close (MYINPUTFILE); close (MYINPUTFILE1); close (MYINPUTFILE2); close (HOST); close (HOST1);
As you can tell, some of the output filenames are also based on the variable input. I am not very experienced with Perl, so any suggestions would be appreciated to the highest levels.

Comment on running multiple loops
Select or Download Code
Re: running multiple loops
by Eliya (Vicar) on Jun 01, 2012 at 14:47 UTC
    It works fine for the first line in file1

    The problem is that once you've read through the files 2 and 3, their file pointers will be at end of file (EOF), so further reads in subsequent iterations of the outer loop return nothing.

    One solution would be to repeatedly seek to the beginning of the files.  Another solution would be to read the contents of file 2 and 3 into arrays.

      Thank you, that solved a large part of my problem. The only issue remaining now is that in files 'host' and 'host1', it only inserts the first line from file3 and leaves it out for subsequent lines.

      The output currently looks like this for 'host':
      SR-IT-SD4546-IBV-sw947-A SR-IT-SD4546-IBV-sw908-A SR-IT-SD4748-IBV-sw-A SR-IT-SD4748-IBV-sw-A
      and like this for 'host1':
      SR-IT-SD4546-IBV-sw947-B SR-IT-SD4546-IBV-sw908-B SR-IT-SD4748-IBV-sw-B SR-IT-SD4748-IBV-sw-B
      The code has been modified to look like this:
      open(MYINPUTFILE, "file1"); open(MYINPUTFILE1, "file2"); open(MYINPUTFILE2, "file3"); open(HOST, ">host"); open(HOST1, ">host1"); while (<MYINPUTFILE>) { my($line) = $_; chomp($line); for ($numsw = $swnum; $numsw > 0 ; $numsw-- ){ my $line1 = <MYINPUTFILE1>; chomp($line1); my $line2 = <MYINPUTFILE2>; chomp($line2); print HOST "SR-$line1-SD$line-IBV-sw$line2-A\n"; print HOST1 "SR-$line1-SD$line-IBV-sw$line2-B\n"; open (OUTHANDLE, ">>$line2"); print OUTHANDLE "SR-$line1-SD$line-IBV-sw$line2-A\n"; print OUTHANDLE "SR-$line1-SD$line-IBV-sw$line2-B\n"; close (OUTHANDLE); seek (partner,0,1); seek (switchid,0,1); } } close (MYINPUTFILE); close (MYINPUTFILE1); close (MYINPUTFILE2); close (HOST); close (HOST1);

      This is the last issue I have to solve before being able to use this for production work, so any additional help is greatly appreciated.

      Here is a solution which outputs the same as you showed us

      It would help us, if you give us a brief explanation of the purpose of your files

      use strict; use warnings; ### ### !!! ALWAYS use strict and warnings !!! ### print "$0 Begin at ", scalar localtime, "\n\n"; open my $hsome_numbers, '<', "File1.text" or die "cannot open file File1"; #File1 should be renamed to something like some_numbers! my @some_numbers = <$hsome_numbers>; #slurp it! close $hsome_numbers; #remember every element of the array now has a line ending at its end, + so chomp! open my $hstring_file, '<', "File2.text" or die "cannot open file File2"; #File2 should be renamed to something like string_file??? #what about the content in string_file, you showed us 7 lines containi +ng "IT"??? #maybe should only unique content be used??? #I decided to only use the unique elements and do a slurp! my @strings = <$hstring_file>; #remember every element of the array now has a line ending at its end, + so chomp! my @uniq_strings; my %seen = (); foreach my $item (@strings) { chomp $item; push(@uniq_strings, $item) unless $seen{$item}++; } # resulting array is @uniq_strings; open my $houtput_files_array, '<', "File3.text" or die "cannot open file File3"; #File3 should be renamed to something like output_files_array! #File3 is an array of filenames, so slurp them! my @filenames = <$houtput_files_array>; close $houtput_files_array; #remember every element of the array now has a line ending at its end, + so chomp! for my $filename (@filenames) { chomp $filename; open my $hout, '>', "${filename}.output" #918.output, 908.outpu +t or die "cannot open file ${filename}.output for writing"; #now you have an output file per line in the array #per line in file some_numbers you want to write the line SR-<line + in string_file>-SD<line in some_numbers>-IBV-sw<line in output_files +_array>-A and the line SR-<>-SD<>-IBV-sw<>-B for my $string (@uniq_strings) { #per (unique) line in line in +string_file for my $number (@some_numbers) { #per line in some_numbers chomp $number; print {$hout} "SR-$string-SD$number-IBV-sw$filename-A\n"; print {$hout} "SR-$string-SD$number-IBV-sw$filename-B\n"; # What you can see here is, that names matter. use variabl +e names coming from your domain, so you will understand your program +better. # Never use anything like file1, file2, line1, line2, this + is BAD style and does not reflect your problem! } } close $hout; print "...processed output file ${filename}.output\n"; } print "$0 Ended at ", scalar localtime, "\n\n"; 1;

      You should be able to make a working program out of this.

      Look at the comments in the code!

      I decided to slurp in every file, maybe this is not the best way to read a multi GByte file

        Thank you, that did it. It works like a champ now.

        As far as what it does, this piece of code is part of a large script that generates configuration files for network elements based on numerous inputs by the user. Some of these inputs include identifiers for various elements, ip addresses, etc. The longest 'final' output i had received thus far was about 29 pages in a word document.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (7)
As of 2014-09-20 14:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (159 votes), past polls