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

I am writing a code which can extract the IPs from a specific text file and make it into one separate text file. So far I am trying to do the following

use Regexp::Common qw/net/; system("clear"); my $file_content = ""; my $parsed = ""; open(INPUT,"<Samplle_2.txt") or die "cannot open Google.txt : $!"; while(<INPUT>){ my $line = $_; chomp($line); $file_content .= $line; } $_ = "\n $file_content"; while(/hops(.+)Trace/mg){ print $1, "\n" if /($RE{net}{IPv4})/; open FILE, ">Google_1" or die $!; print FILE "Important Information \n $1"; close FILE; }

The new file just gives me the first IP mentioned in the file, any idea about this?

My file format looks something like the following

;ANSWER 1.chstatic.cvcdn.com. 2699 IN CNAME d2cc2sq9kkgwfv.cloudfront.net. d2cc2sq9kkgwfv.cloudfront.net. 37 IN CNAME d2cc2sq9kkgwfv.lhr5.cloudfr +ont.net. d2cc2sq9kkgwfv.lhr5.cloudfront.net. 37 IN A 54.240.166.179 d2cc2sq9kkgwfv.lhr5.cloudfront.net. 37 IN A 54.240.166.100 d2cc2sq9kkgwfv.lhr5.cloudfront.net. 37 IN A 54.240.166.189 d2cc2sq9kkgwfv.lhr5.cloudfront.net. 37 IN A 54.240.166.183 d2cc2sq9kkgwfv.lhr5.cloudfront.net. 37 IN A 54.240.166.77 d2cc2sq9kkgwfv.lhr5.cloudfront.net. 37 IN A 54.240.166.209 d2cc2sq9kkgwfv.lhr5.cloudfront.net. 37 IN A 54.240.166.186 d2cc2sq9kkgwfv.lhr5.cloudfront.net. 37 IN A 54.240.166.123 ;AUTHORITY ;ADDITIONAL Traceroute: 10 1339258888 1339258869 1339258869 LocalDNS LocalDNS 10.7 +1.165.25 Tracing route to 10.71.165.25 over a maximum of 20 hops 1 139 ms 89 ms 114 ms 10.94.1.6 2 134 ms 129 ms 99 ms 10.130.100.1 3 119 ms 129 ms 109 ms 10.130.100.177 4 113 ms 119 ms 90 ms 10.71.165.25 Trace complete. Query: 23 1339258888 LocalDNS 1.chstatic.cvcdn.com 1 True 0.2893088367 +38 0.326385895414 id 34054 opcode QUERY rcode NOERROR flags QR RD RA ;QUESTION

And i just need the IPs from line 1, 2, 3, 4 and don't want the IPs that are above.... Any thought on this

Replies are listed 'Best First'.
Re: Writing a new file in Perl
by zwon (Abbot) on Jul 05, 2012 at 11:12 UTC
    while(/hops(.+)Trace/mg){ print $1, "\n" if /($RE{net}{IPv4})/; open FILE, ">Google_1" or die $!; print FILE "Important Information \n $1"; close FILE; }

    Each time you call open, the file gets truncated. Either open it before the loop, and close after the loop, or open file for appending:

    open FILE, ">>Google_1" or die $!
Re: Writing a new file in Perl
by aaron_baugher (Curate) on Jul 05, 2012 at 13:00 UTC

    There's a lot about this that could be improved, but here's your specific problem:

    while(/hops(.+)Trace/mg){ print $1, "\n" if /($RE{net}{IPv4})/;
    Your while loop grabs the text between "hops" and "Trace", which includes the whole output of a traceroute. The second line searches that for an IPv4 address, and if one is found, prints it. It only searches once, so only one will be found. To make it search repeatedly, you need to give it the 'g' modifier, and put it in a loop:

    print "$1\n" for /($RE{net}{IPv4})/g;

    Aaron B.
    Available for small or large Perl jobs; see my home node.

      Is it possible that each trace route is separated by some kind of word or something so that when I am processing them they can differentiated from one another. Actually I am mapping them, therefore they need to be differentiated from each other.

        Well, we can't tell you that without seeing a sample file with more than one traceroute in it. But I suspect you could split the records on something, yes. For instance, splitting your file on the string "Tracing route to" looks like it would probably break the file into chunks containing no more than one trace each.

        Aaron B.
        Available for small or large Perl jobs; see my home node.

Re: Writing a new file in Perl
by daxim (Curate) on Jul 05, 2012 at 11:09 UTC
    use strictures; use Regexp::Common qw/net/; use autodie qw(:all); open my $in, '<:raw', 'Samplle_2.txt'; open my $out, '>:raw', 'Google_1'; while (my $line = <$in>) { my ($ip) = $line =~ /(?: \d+ [ ] ms \s+ ){3} ($RE{net}{IPv4})/msx; print {$out} "$ip\n" if defined $ip; }

      Can you explain a bit what have you done here?

        What if the text file in the following format?

        ns2.imagebam.com. 288 IN A 208.100.30.161 ns3.imagebam.com. 288 IN A 80.237.155.76 Traceroute: 7 1291796828 1291796823 1291796823 LocalDNS 0.media.colleg +ehumor.com 92.123.72.112 traceroute to 92.123.72.112 (92.123.72.112), 30 hops max, 60 byte pack +ets 1 192.168.178.1 0.577 ms * * 2 82.135.16.28 43.200 ms 47.166 ms 51.078 ms 3 212.18.7.101 55.219 ms 58.215 ms 62.163 ms 4 212.18.6.166 70.082 ms 74.198 ms 78.128 ms 5 80.81.192.28 83.097 ms 86.971 ms 90.658 ms 6 92.123.72.112 94.970 ms 102.063 ms 66.001 ms Traceroute: 14 1291796828 1291796823 1291796823 OpenDNS 0.media.colleg +ehumor.com 62.41.85.112 traceroute to 62.41.85.112 (62.41.85.112), 30 hops max, 60 byte packet +s 1 * * * 2 82.135.16.28 42.731 ms 45.991 ms 50.306 ms 3 212.18.7.101 56.221 ms 58.592 ms 62.741 ms 4 212.18.6.77 65.781 ms 70.059 ms 74.070 ms 5 217.71.108.93 80.675 ms 84.516 ms 92.326 ms 6 217.71.96.169 97.099 ms 61.316 ms 61.671 ms 7 194.59.190.3 68.525 ms 66.420 ms 67.461 ms 8 134.222.231.49 69.524 ms 70.433 ms 69.926 ms 9 134.222.229.49 70.076 ms 66.691 ms 67.396 ms 10 134.222.229.205 80.651 ms 79.661 ms 76.400 ms 11 134.222.229.222 77.579 ms 71.688 ms 71.845 ms 12 134.222.231.22 71.431 ms 70.759 ms 134.222.231.226 70.182 ms 13 62.41.85.112 70.377 ms 70.854 ms 70.851 ms Traceroute: 10 1291796828 1291796823 1291796823 OpenDNS 0.media.colleg +ehumor.com 213.155.157.35 traceroute to 213.155.157.35 (213.155.157.35), 30 hops max, 60 byte pa +ckets

      The {} isn't needed here

      print {$out} "$ip\n" if defined $ip;

      You can write  print $out "$ip\n";

        It is good style to wrap the dative object in braces.