in reply to Re^2: Printing first and last line
in thread Printing first and last line

Hello maheshkumar, and welcome to the Monastery!

i am getting 80800

Yes, you’re getting the wrong answer there, but before that you are also getting 136 warnings of the form:

Use of uninitialized value $destination_IP in string ne at...

which should act as a red flag that your logic is wrong somewhere. Never ignore warnings! They are there to help you.

Now, the problem with your script is that it’s finding lines like this:

ns1.sina.com.cn. 80800 IN A 202.106.184.166

which come after the list of IP addresses you are interested in. So, you need some way of turning off the search when the list has ended. Here is one possible algorithm:

clear in_list flag FOR each line in the data file IF line matches first line of a list THEN extract IP save IP as source set in_list flag ELSE IF in_list flag set THEN SWITCH line CASE line matches second list line ignore it CASE line matches list-address save addresses, indexed to current source CASE default (i.e. no longer in list) clear in_list flag ENDSWITCH ENDIF ENDELSE ENDFOR

Here is an implementation in Perl:

#! perl use strict; use warnings; my $line1_re = qr! ^ Traceroute: \s+ .* \s+ (\S+) $ !x; my $line2_re = qr! ^ traceroute !x; my $destn_re = qr! ^ # start of line \s* # optional whitesp +ace \d+ # sequence number: + nnn \s+ # whitespace (?: # EITHER (?: \d{1,3} \. ){3} \d{1,3} # IP address: nn +n.nnn.nnn.nnn | # OR \* \s+ \* \s+ \* # * * * ) !x; my (%ipToRoute, $source_IP, $in_tracing); while (my $line = <DATA>) { chomp $line; if ($line =~ /$line1_re/) { $source_IP = $1; $in_tracing = 1; } elsif ($in_tracing && $line !~ /$line2_re/) { if ($line =~ /$destn_re/) { $line =~ s/ ^ \s+ //x; my $destination_IP = (split /\s+/, $line)[1]; push @{ $ipToRoute{$source_IP} }, $destination_IP unless $destination_IP eq '*'; } else { $in_tracing = 0; } } } foreach (keys %ipToRoute) { my $final_destination = @{ $ipToRoute{$_} }[-1]; printf "Destination to %s but reached %s\n", $_, $final_destination unless $_ eq $final_destination; } __DATA__ Traceroute: 22 1291136399 1291136393 1291136393 LocalDNS home.china.co +m.cn 221.204.248.107 traceroute to 221.204.248.107 (221.204.248.107), 30 hops max, 60 byte +packets 1 134.2.173.254 0.170 ms 0.191 ms 0.185 ms etc.

With the data you supplied, this outputs:

Destination to 92.123.72.112 but reached 92.123.72.0 Destination to 78.108.81.20 but reached 217.106.1.146 Destination to 208.78.244.38 but reached 208.78.244.0

as required. Note: For improved readability, I have extracted the regular expressions using the qr operator, and annotated the third one because of its complexity.

HTH,

Athanasius <°(((><contra mundum

Replies are listed 'Best First'.
Re^4: Printing first and last line
by maheshkumar (Sexton) on Aug 14, 2012 at 13:13 UTC

    Thank you so much for the head start, I tried to modify the code according to the following format

    Traceroute: 20 1291140121 1291140102 1291140102 LocalDNS 4.bp.blogspot +.com 74.125.127.102 Tracing route to 74.125.127.102 over a maximum of 20 hops 1 1 ms * 1 ms 192.168.1.1 2 14 ms 8 ms 9 ms 73.220.38.1 3 9 ms 9 ms 11 ms 68.87.207.65 4 21 ms 13 ms 13 ms 68.85.240.101 5 11 ms 17 ms 12 ms 68.85.240.94 6 15 ms 12 ms 13 ms 68.86.93.109 7 13 ms 14 ms 15 ms 68.86.85.205 8 17 ms 14 ms 13 ms 68.86.85.42 9 14 ms 13 ms 12 ms 75.149.231.90 10 16 ms 15 ms 18 ms 209.85.249.32 11 16 ms 13 ms 14 ms 66.249.94.195 12 23 ms 20 ms 21 ms 216.239.46.200 13 24 ms 23 ms 20 ms 64.233.174.103 14 72 ms 58 ms 22 ms 216.239.46.18 15 23 ms 19 ms 24 ms 74.125.127.102 Trace complete. Query: 11 1291140122 GoogleDNS 52.mgl.skyrock.net 1 True 0.28404291513 +2 0.218060020179 id 43103 opcode QUERY rcode NOERROR flags QR RD RA ;QUESTION 52.mgl.skyrock.net. IN A ;ANSWER 52.mgl.skyrock.net. 562 IN CNAME mgl50.gslb.skyrock.net. mgl50.gslb.skyrock.net. 10 IN A 91.203.186.8 ;AUTHORITY ;ADDITIONAL Query: 11 1291140122 GoogleDNS 52.mgl.skyrock.net 1 True 0.09980143832 +56 0.203481721767 id 37287 opcode QUERY rcode NOERROR flags QR RD RA ;QUESTION 52.mgl.skyrock.net. IN A ;ANSWER 52.mgl.skyrock.net. 562 IN CNAME mgl50.gslb.skyrock.net. mgl50.gslb.skyrock.net. 10 IN A 91.203.186.8 ;AUTHORITY ;ADDITIONAL Query: 13 1291140122 OpenDNS 6.media.collegehumor.com 1 True 0.2016434 +86473 0.0180179321429 id 21546 opcode QUERY rcode NOERROR flags QR RD RA ;QUESTION 6.media.collegehumor.com. IN A ;ANSWER 6.media.collegehumor.com. 600 IN CNAME 6.media.collegehumor.com.edgesu +ite.net. 6.media.collegehumor.com.edgesuite.net. 21600 IN CNAME a1835.g.akamai. +net. a1835.g.akamai.net. 1 IN A 209.107.205.50 a1835.g.akamai.net. 1 IN A 209.107.205.51 ;AUTHORITY ;ADDITIONAL Query: 13 1291140122 OpenDNS 6.media.collegehumor.com 1 True 0.0797040 +345855 0.0161269034938 id 29064 opcode QUERY rcode NOERROR flags QR RD RA ;QUESTION 6.media.collegehumor.com. IN A ;ANSWER 6.media.collegehumor.com. 600 IN CNAME 6.media.collegehumor.com.edgesu +ite.net. 6.media.collegehumor.com.edgesuite.net. 21600 IN CNAME a1835.g.akamai. +net. a1835.g.akamai.net. 1 IN A 209.107.205.50 a1835.g.akamai.net. 1 IN A 209.107.205.51 ;AUTHORITY ;ADDITIONAL Traceroute: 18 1291140122 1291140104 1291140104 GoogleDNS 4.media.coll +egehumor.com 92.122.217.179 Tracing route to 92.122.217.179 over a maximum of 20 hops 1 1 ms * 1 ms 192.168.1.1 2 11 ms 10 ms 8 ms 73.220.38.1 3 8 ms 7 ms 11 ms 68.87.207.65 4 24 ms 10 ms 8 ms 68.85.240.101 5 8 ms 10 ms 9 ms 68.85.240.94 6 21 ms 14 ms 14 ms 68.86.93.109 7 27 ms 27 ms 26 ms 68.86.85.162 8 29 ms 30 ms 32 ms 68.86.85.46 9 34 ms 32 ms 32 ms 68.86.87.6 10 29 ms 31 ms 30 ms 80.156.163.153 11 191 ms 243 ms 257 ms 62.154.5.25 12 186 ms 189 ms 204 ms 80.146.198.54 13 227 ms 193 ms 214 ms 92.122.217.179 Trace complete.

    I think so I have written the right Regular Expressions but am not getting the output. Here is the code i modified from yours. Only the part where you are defining the lines format.

    my $line1_re = qr! ^ Traceroute: \s+ .* \s+ (\S+) $ !x; my $line2_re = qr! ^ Tracing route !x; my $destn_re = qr! ^ \s*\d+(\s+\d+\sms \s+){3} (?:(?: \d{1,3} \. ){3} +\d{1,3}|(/*/) )!x;

      This new data format is a good candidate for the "flip-flop" operator:

      use strict; use warnings; my ($want, $got); while(<DATA>){ if (/Tracing route to/ .. /Trace complete/) { if (/Tracing route to ((?:\d+\.){3}\d+)/) { $want = $1; } elsif (/((?:\d+\.){3}\d+)/){ $got = $1; } elsif (/Trace complete/) { print "wanted $want, got $got\n"; $want = $got = ""; } } } __DATA__ Traceroute: 20 1291140121 1291140102 1291140102 LocalDNS 4.bp.blogspot +.com 74.125.127.102 Tracing route to 74.125.127.102 over a maximum of 20 hops 1 1 ms * 1 ms 192.168.1.1 2 14 ms 8 ms 9 ms 73.220.38.1 3 9 ms 9 ms 11 ms 68.87.207.65 4 21 ms 13 ms 13 ms 68.85.240.101 5 11 ms 17 ms 12 ms 68.85.240.94 6 15 ms 12 ms 13 ms 68.86.93.109 7 13 ms 14 ms 15 ms 68.86.85.205 8 17 ms 14 ms 13 ms 68.86.85.42 9 14 ms 13 ms 12 ms 75.149.231.90 10 16 ms 15 ms 18 ms 209.85.249.32 11 16 ms 13 ms 14 ms 66.249.94.195 12 23 ms 20 ms 21 ms 216.239.46.200 13 24 ms 23 ms 20 ms 64.233.174.103 14 72 ms 58 ms 22 ms 216.239.46.18 15 23 ms 19 ms 24 ms 74.125.127.102 Trace complete. Query: 11 1291140122 GoogleDNS 52.mgl.skyrock.net 1 True 0.28404291513 +2 0.218060020179 id 43103 opcode QUERY rcode NOERROR flags QR RD RA ;QUESTION 52.mgl.skyrock.net. IN A ;ANSWER 52.mgl.skyrock.net. 562 IN CNAME mgl50.gslb.skyrock.net. mgl50.gslb.skyrock.net. 10 IN A 91.203.186.8 ;AUTHORITY ;ADDITIONAL Query: 11 1291140122 GoogleDNS 52.mgl.skyrock.net 1 True 0.09980143832 +56 0.203481721767 id 37287 opcode QUERY rcode NOERROR flags QR RD RA ;QUESTION 52.mgl.skyrock.net. IN A ;ANSWER 52.mgl.skyrock.net. 562 IN CNAME mgl50.gslb.skyrock.net. mgl50.gslb.skyrock.net. 10 IN A 91.203.186.8 ;AUTHORITY ;ADDITIONAL Query: 13 1291140122 OpenDNS 6.media.collegehumor.com 1 True 0.2016434 +86473 0.0180179321429 id 21546 opcode QUERY rcode NOERROR flags QR RD RA ;QUESTION 6.media.collegehumor.com. IN A ;ANSWER 6.media.collegehumor.com. 600 IN CNAME 6.media.collegehumor.com.edgesu +ite.net. 6.media.collegehumor.com.edgesuite.net. 21600 IN CNAME a1835.g.akamai. +net. a1835.g.akamai.net. 1 IN A 209.107.205.50 a1835.g.akamai.net. 1 IN A 209.107.205.51 ;AUTHORITY ;ADDITIONAL Query: 13 1291140122 OpenDNS 6.media.collegehumor.com 1 True 0.0797040 +345855 0.0161269034938 id 29064 opcode QUERY rcode NOERROR flags QR RD RA ;QUESTION 6.media.collegehumor.com. IN A ;ANSWER 6.media.collegehumor.com. 600 IN CNAME 6.media.collegehumor.com.edgesu +ite.net. 6.media.collegehumor.com.edgesuite.net. 21600 IN CNAME a1835.g.akamai. +net. a1835.g.akamai.net. 1 IN A 209.107.205.50 a1835.g.akamai.net. 1 IN A 209.107.205.51 ;AUTHORITY ;ADDITIONAL Traceroute: 18 1291140122 1291140104 1291140104 GoogleDNS 4.media.coll +egehumor.com 92.122.217.179 Tracing route to 92.122.217.179 over a maximum of 20 hops 1 1 ms * 1 ms 192.168.1.1 2 11 ms 10 ms 8 ms 73.220.38.1 3 8 ms 7 ms 11 ms 68.87.207.65 4 24 ms 10 ms 8 ms 68.85.240.101 5 8 ms 10 ms 9 ms 68.85.240.94 6 21 ms 14 ms 14 ms 68.86.93.109 7 27 ms 27 ms 26 ms 68.86.85.162 8 29 ms 30 ms 32 ms 68.86.85.46 9 34 ms 32 ms 32 ms 68.86.87.6 10 29 ms 31 ms 30 ms 80.156.163.153 11 191 ms 243 ms 257 ms 62.154.5.25 12 186 ms 189 ms 204 ms 80.146.198.54 13 227 ms 193 ms 214 ms 92.122.217.179 Trace complete.

      Prints:

      wanted 74.125.127.102, got 74.125.127.102 wanted 92.122.217.179, got 92.122.217.179
        I am not sure but it is not working - any ideas?
        for example 192.168.2.1 reached to 192.168.2.1 so i dont need that, it is giving me that result as well

      Hello again, maheshkumar,

      If I understand correctly, the format of your input data has now changed, with blank lines inserted and a line reading “Trace complete.” following each list of traceroutes. And you have tried to adapt the code I gave by changing 2 of the regular expressions.

      Well, your change to $line2_re is fine, but $destn_re now has (/*/) which only matches a forward slash followed immediately by an asterisk followed immediately by another forward slash — which doesn’t match your data. I think you want something like this (untested):

      # Example lines: # 1 1 ms * 1 ms 192.168.1.1 # 2 14 ms 8 ms 9 ms 73.220.38.1 my $destn_re = qr! ^ # start of line \s* \d+ \s+ ms # 14 ms (?: # EITHER (?: \d+ ms ) # 8 ms | # OR \* # * ) \s+ \d+ \s+ ms # 9 ms \s+ (?: \d{1,3} \. ){3} \d{1,3} # IP address: 192. +168.1.1 $ # end of line !x;

      You should study perlretut and then perlre to get a solid understanding of regular expressions.

      However, the real problem is that the algorithm needs to be changed to match the new input format. Hint: add a CASE for blank lines, and change CASE default to match lines beginning Trace complete. (But there might be other approaches which would work just as well.) First get the algorithm clear: work it out on paper, going through the input data, and verify that the steps in the new algorithm lead to the desired result. Once you have the algorithm worked out, you will find adapting the Perl code is quite straightforward.

      Keep at it, you’re making progress!

      Update 1: Fixed and annotated regex in response to OP’s question, below.

      Update 2: ++hbm for the solution below using Perl’s “flip-flop” operator.

      Athanasius <°(((><contra mundum

        There will be 3 (ms) right as ms appears thrice so are you missing one in the one that you have put?

Re^4: Printing first and last line
by maheshkumar (Sexton) on Aug 15, 2012 at 10:19 UTC

    Just one last quick question what i am trying to do is to compare the two IPs if the first three octet are similar or not. For example Destination to 92.123.72.112 but reached 92.123.72.0 in this the first three are similar that means 92.123.72 are same so i want to put these two IPs in a hash and the key to them will be their location which i will find with another code. How is this possible?

      I think the following little script should be enough to show you how to proceed:

      #! perl use strict; use warnings; use diagnostics; use Data::Dumper; my $destination = '92.123.72.112'; my $final_ip = '92.123.72.0'; # Get the first 3 octets of each IP my $destn_prefix = $destination =~ s/ \. \d{1,3} $ //rx; my $final_prefix = $final_ip =~ s/ \. \d{1,3} $ //rx; # Populate the hash my %hash; if ($destn_prefix eq $final_prefix) { $hash{$destn_prefix} = [ $destination, $final_ip ]; } print Dumper(\%hash), "\n"; # Access a given location my $ip = '92.123.72'; if (exists $hash{$ip}) { my @ips = @{ $hash{$ip} }; print 'IPs at location ', $ip, ' are: ', join(', ', @ips), "\n"; }

      Output:

      $VAR1 = { '92.123.72' => [ '92.123.72.112', '92.123.72.0' ] }; IPs at location 92.123.72 are: 92.123.72.112, 92.123.72.0

      Some useful references:

      Hope that helps,

      Athanasius <°(((><contra mundum