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

I have a file containing the output after pinging several IP addresses. For example, the first line is "12.34.56.78 is alive" and line 2 is "no answer from 12.34.56.79" and so on. I am trying to print only those lines that contain the words "is alive." I tried several things including grep and if-else statements but only want those lines containing "is alive" to print to a separate file & am having no luck. Heres what I have so far:
# Create a list of all possible IP addresses within subnet open(ALLIP, ">allip.list") || die "Unable to create file: allip.list\n +"; for ($i=0; $i<=20; $i++) { print ALLIP "$ip_subnet.$i\n"; } close(ALLIP); open(ALLIP, "allip.list") || die "Unable to open file: allip.list\n"; open(PINGALLIP, ">pingallip.list") || die "Unable to open file: pingal +lip.list"; while (<ALLIP>) { chomp; system("ping $_ >>pingallip.list") && "Unable to create file: +pingallip. list"; } close(ALLIP); close(PINGALLIP); open(ALIVEIP, ">aliveip.list"); close(ALIVEIP); open(ALIVEIP, "aliveip.list"); open(PINGALLIP, "pingallip.list") || die "Unable to open file: pingall +ip.list"; while (<PINGALLIP>) { if (/is alive/) { chomp; print ALIVEIP $_; } } close(PINGALLIP);
Any help would be greatly appreciated. The idea of using the IP module has already been mentioned to me but I am also using this as an excuse to improve my perl skills. =) Thanks.

Zuinc

Replies are listed 'Best First'.
Re: Printing matched lines
by perlplexer (Hermit) on Apr 09, 2002 at 18:35 UTC
    grep 'is alive' log.dat > out.dat

    Or if you really want to do this in Perl:
    # Assuming file name is in $ARGV[0] while(<>){ print if /is alive/; }
    or just

    perl -ne "print if /is alive/" log.dat > out.dat

    --perlplexer
Re: Printing matched lines
by Kanji (Parson) on Apr 09, 2002 at 18:39 UTC

    If your code is cut-n-pasted, part of your problem lies in the snippet below, where you re-open the file you plan on printing to, but as read-only.

    open(ALIVEIP, ">aliveip.list"); close(ALIVEIP); open(ALIVEIP, "aliveip.list");

    Also, do you really need to chomp when reading from <PINGALLIP>? If you want each message printed on a line by itself, you can just use...

    while ( my $line = <PINGALLIP>) { print ALIVEIP $line if $line =~ /is alive/; }

        --k.


Re: Printing matched lines
by emilford (Friar) on Apr 09, 2002 at 18:38 UTC
    I think your best bet would be to use Perl's match operator, but then again one of the other monks might have a better solution (I'm still learning!). I just setup a little test text file and wrote a few lines of code (below) and it does what you were asking for.
    Text file --------------------------------------- 1234567 is alive 12345678 is not alive 123456789 is alive<br><br> Code --------------------------------------- #! /usr/bin/perl -w use strict; open(FILE, ">test.txt") || die "Unable to open file: $!"; chomp (my @input = <FILE>); # store lines in array, removing CRLF close(FILE); foreach my $line (@input) { if($line =~ m/is alive/) { print "$line\n"; } } Output ------------------------------------- 1234567 is alive 123456789 is alive
    Hope this helps!! -Eric
Re: Printing matched lines
by Zaxo (Archbishop) on Apr 09, 2002 at 18:36 UTC

    while is not setting $_ for you. in

    while (<PINGALLIP>) { if (/is alive/) { chomp; print ALIVEIP $_; } }
    Try this instead:
    /is alive/ and print ALIVEIP for <PINGALLIP>;
    If the match is true then print $_ for all lines. I omitted chomp since the record delimiters will probably be handy in the file.

    After Compline,
    Zaxo

Re: Printing matched lines
by dug (Chaplain) on Apr 09, 2002 at 18:36 UTC
    change:
    while (<PINGALLIP>) { if (/is alive/) { chomp; print ALIVEIP $_; } }
    to:
    while (<PINGALLIP>) { if ($_ =~ /is alive/) { chomp; print ALIVEIP $_; } }
    That will apply the m// operator to magic variable $_, which is the current line of your while loop.
A reply falls below the community's threshold of quality. You may see it by logging in.