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

This one will drive me crazy. I have multiple input files, all containing the same number of lines. What I need to do is use all "line one" inputs, then all "line two" inputs, etc. While the below code does what it is supposed to with the last file, it never moves to line 2 of the first file. Any ideas?
print HDLCGET "\#\!\/usr\/local\/bin\/expect\n"; print HDLCGET "set timeout -1\n"; open(MYINPUTFILE, "hdlc2"); open(MYINPUTFILE1, "hdlc3"); while(<MYINPUTFILE>) { my($line) = $_; chomp($line); while(<MYINPUTFILE1>) { my($line1) = $_; chomp($line1); print HDLCGET "spawn \ ssh $line\n"; print HDLCGET "expect \"assword: \"\n"; print HDLCGET "send \"$tacacspw\\r\"\n"; print HDLCGET "expect \"#\"\n"; print HDLCGET "send \"terminal length 0\\r\"\n"; print HDLCGET "expect \"#\"\n"; print HDLCGET "send \"show xconnect all | inc $line1\\r\"\nexp +ect \"#\"\n"; print HDLCGET "send \"exit\\r\"\n"; print HDLCGET "interact\n"; } } close(MYINPUTFILE); close(MYINPUTFILE1);
Here is what I get from that code, I noted the inputs and the error:
#!/usr/local/bin/expect set timeout -1 spawn ssh 10.247.17.141 <-- line 1 of hdlc2 expect "assword: " send "tacacspw\r" expect "#" send "terminal length 0\r" expect "#" send "show xconnect all | inc 99999999\r" <--line 1 of hdlc3 expect "#" send "exit\r" interact spawn ssh 10.247.17.141 <--LINE 1 OF hdlc2, SHOULD BE LINE 2 expect "assword: " send "Kalewi13\r" expect "#" send "terminal length 0\r" expect "#" send "show xconnect all | inc 616698950\r" <--line 2 of hdlc3 expect "#" send "exit\r" interact
Also, while I'm using 2 input files here, later on I will have to use 4 input files, but I haven't gotten to that part yet, and I figured the same logic should apply

Replies are listed 'Best First'.
Re: Using multiple input files #2
by Corion (Patriarch) on Mar 31, 2009 at 16:54 UTC

    Nested loops mean that for every line in the outer loop, the inner loop will run once. You're not walking through the two files in parallel, as you see.

    Why don't you just read both files into two arrays and iterate over the arrays?

Re: Using multiple input files #2
by kennethk (Abbot) on Mar 31, 2009 at 16:54 UTC

    Since your loops are nested, you move through the entirety of file2 before you go to the second line of file1. Perhaps you mean something more like (untested):

    print HDLCGET "\#\!\/usr\/local\/bin\/expect\n"; print HDLCGET "set timeout -1\n"; open(MYINPUTFILE, "<", "hdlc2") or die "Open MYINPUTFILE failed: $!"; open(MYINPUTFILE1, "<", "hdlc3") or die "Open MYINPUTFILE1 failed: $!" +; while(<MYINPUTFILE>) { my($line) = $_; chomp($line); #my($line1) = <MYINPUTFILE1>; # This slurps the file - oops my $line1 = <MYINPUTFILE1>; chomp($line1); print HDLCGET "spawn \ ssh $line\n"; print HDLCGET "expect \"assword: \"\n"; print HDLCGET "send \"$tacacspw\\r\"\n"; print HDLCGET "expect \"#\"\n"; print HDLCGET "send \"terminal length 0\\r\"\n"; print HDLCGET "expect \"#\"\n"; print HDLCGET "send \"show xconnect all | inc $line1\\r\"\nexpect +\"#\"\n"; print HDLCGET "send \"exit\\r\"\n"; print HDLCGET "interact\n"; } close(MYINPUTFILE); close(MYINPUTFILE1);

    Note also I swapped to the three-argument form of open and added a test to make sure the open succeeded - part of the same advice toolic gave you in Re: using multiple input files. Also, you might read How do I post a question effectively?, as debugging file-processing code w/o the files to be processed can be tricky.

    Update: As discussed below, the above code was buggy. Corrected the error and kept the original line as a comment for posterity.

      I appreciate the advise. It now moves nicely thru the first file. However, it only reads the first line of the second file, and leaves subsequent fields blank, as shown below. Also, to help out, I added the content of both input files as well.
      print HDLCGET "\#\!\/usr\/local\/bin\/expect\n"; print HDLCGET "set timeout -1\n"; open(MYINPUTFILE, "hdlc2") or die "UNABLE TO OPEN FILE hdlc2: $!"; open(MYINPUTFILE1, "hdlc3") or die "UNABLE TO OPEN FILE hdlc3: $!"; while(<MYINPUTFILE>) { my($line) = $_; chomp($line); my($line1) = <MYINPUTFILE1>; chomp($line1); print HDLCGET "spawn \ ssh $line\n"; print HDLCGET "expect \"assword: \"\n"; print HDLCGET "send \"$tacacspw\\r\"\n"; print HDLCGET "expect \"#\"\n"; print HDLCGET "send \"terminal length 0\\r\"\n"; print HDLCGET "expect \"#\"\n"; print HDLCGET "send \"show xconnect all | inc $line1\\r\"\nexpect +\"#\"\n"; print HDLCGET "send \"exit\\r\"\n"; print HDLCGET "interact\n"; } close(MYINPUTFILE); close(MYINPUTFILE1);
      now gives me the following output:
      #!/usr/local/bin/expect set timeout -1 spawn ssh 10.247.17.141 expect "assword: " send "Kalewi13\r" expect "#" send "terminal length 0\r" expect "#" send "show xconnect all | inc 99999999\r" expect "#" send "exit\r" interact spawn ssh 10.247.17.1 expect "assword: " send "Kalewi13\r" expect "#" send "terminal length 0\r" expect "#" send "show xconnect all | inc \r" <-- MISSING LINE 2 INPUT FROM hdlc +3 expect "#" send "exit\r" interact
      here is the content of the two input files. I kept it to three lines for now.

      hdlc2
      10.247.17.141 10.247.17.1 10.247.17.69
      hdlc3
      99999999 616698950 615498584
      Thanks again for the help.

        Found the issue, which was my fault. By surrounding $line1 with parentheses in my($line1) = <MYINPUTFILE1>;, we moved to list-context. This means the entire file was being slurped, and the first element of the resulting list (i.e. line 1) was stored to the variable. On the subsequent iterations, the result was undef because the entire file had been read already. Working code:

        use warnings; use strict; my $tacacspw = 'Kalewi13'; print "\#\!\/usr\/local\/bin\/expect\n"; print "set timeout -1\n"; open(MYINPUTFILE, "<", "hdlc2") or die "UNABLE TO OPEN FILE hdlc2: $!" +; open(MYINPUTFILE1, "<", "hdlc3") or die "UNABLE TO OPEN FILE hdlc3: $! +"; while(<MYINPUTFILE>) { my($line) = $_; chomp($line); my $line1 = <MYINPUTFILE1>; chomp($line1); print "spawn \ ssh $line\n"; print "expect \"assword: \"\n"; print "send \"$tacacspw\\r\"\n"; print "expect \"#\"\n"; print "send \"terminal length 0\\r\"\n"; print "expect \"#\"\n"; print "send \"show xconnect all | inc $line1\\r\"\nexpect \"#\"\n" +; print "send \"exit\\r\"\n"; print "interact\n"; } close(MYINPUTFILE); close(MYINPUTFILE1);