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

Hello Monks, i am new to Perl and am confused on an issue. I have a script that is using two files as input. One contains backup jobnames and the other contains a list of server names. My goal is to use the server names to grep backup jobnames. The script works fine the first time around but does not grep the second backup job (verified it exists). Here is my Perl code:

#!/usr/bin/perl use warnings; use strict; system "autorep -J NB% | egrep -v \"Job Name|___\" | awk '{print \$1}' + | sed '/^\$/d' | sort > NB_JIL.txt"; chomp(my @server_names = <>); open NB_FILE, '<', "/users/home/mkar/Perl_scripts/NB_JIL.txt" or die " +Couldn't open Netbackup file!"; my $iteration_number = 1; for my $backup_job (@server_names) { print ":$iteration_number:\n"; print "$backup_job\n"; print (grep /$backup_job/, <NB_FILE>); $iteration_number ++; } close NB_FILE or die "Couldn't close the file properly!"

This is what it produces:

> ./test.pl test.txt :1: puccini NB_ISA_SNOH_puccini_DB_diff NB_ISA_SNOH_puccini_DB_full :2: cgndsdr4 >
What am I doing wrong? Thank you in advance !

Replies are listed 'Best First'.
Re: Help with for loop
by BrowserUk (Patriarch) on Sep 12, 2013 at 02:22 UTC
    What am I doing wrong?

    You are expecting to be able to re-read your file each time you iterate your for loop. But that is not how IO works (in any language).

    Files read from beginning to end and then stop.

    If you want to re-read your file each time around your for loop, you will need to either:

    • Re-open the file each time.

      Ie. put the open & close inside the for loop.

    • Or "rewind" the file each time you iterate the for loop.

      Ie. Add a line: seek NB_FILE, 0, 0; as the first line inside the for loop.

      See seek() for details.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Help with for loop
by Athanasius (Archbishop) on Sep 12, 2013 at 02:30 UTC

    If the file is not too big, it will be more efficient to read the file just once, into an array:

    open NB_FILE, '<', '/users/home/mkar/Perl_scripts/NB_JIL.txt' or die " +Couldn't open Netbackup file!: $!"; my @nb = <NB_FILE>; close NB_FILE or die "Couldn't close the file properly!: $!"

    and then grep the array: grep /$backup_job/, @nb within the for loop.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: Help with for loop
by NetWallah (Canon) on Sep 12, 2013 at 05:29 UTC
    Suggestions:

    1. To avoid the IO overhead of creating, then reading the file (which, presumably you do not need for other purposes),
    you can pipe the command output directly into a perl filehandle using a construct like:

    open(my $netbackup, "-|", "autorep -J NB\%") or die could not open net +backup:$!"; while (<$netbackup>){ next if m/Job Name|____/; # do the equivalent of sed #Presumably, you don't need sort # If you do, you can apply filters, accumulate, THEN sort in perl. } close $netbackup;
    2. Since you have already read in @server_names, you can grep each of those to find if any are in the line read from $netbackup, and process it.

                 My goal ... to kill off the slow brain cells that are holding me back from synergizing my knowledge of vertically integrated mobile platforms in local cloud-based content management system datafication.

Re: Help with for loop
by Laurent_R (Canon) on Sep 12, 2013 at 06:46 UTC

    This line of code:

        print (grep /$backup_job/, <NB_FILE>);

    reads the whole file and positions the filehandler at the end of the file. Therefore, next time in the for loop, you don't read anything from the file. You should probazbly loazd your file into an array and then read through the aerray.

Re: Help with for loop
by Anonymous Monk on Sep 12, 2013 at 02:20 UTC
Re: Help with for loop
by uday_sagar (Scribe) on Sep 12, 2013 at 09:16 UTC

    Hello,

    Actually, for each iteration in the for loop you are done with NB_FILE. In that case, you have to take fresh NB_FILE. This is one way of doing!

    #!/usr/bin/perl use warnings; use strict; system "autorep -J NB% | egrep -v \"Job Name|___\" | awk '{print \$1}' + | sed '/^\$/d' | sort > NB_JIL.txt"; chomp(my @server_names = <>); my $iteration_number = 1; for my $backup_job (@server_names) { open NB_FILE, '<', "/users/home/mkar/Perl_scripts/NB_JIL.txt" or die " +Couldn't open Netbackup file!"; print ":$iteration_number:\n"; print "$backup_job\n"; print (grep /$backup_job/, <NB_FILE>); $iteration_number ++; close NB_FILE or die "Couldn't close the file properly!" }