Regular expression to find senders IP using grep or other languages

1

I have input file that contains:

19:04:01.631948 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [none], proto UDP (17), length 48)
181.173.82.61.1985 > 250.66.33.195.1985: HSRPv0-hello 20: state=active group=72 addr=171.64.72.1 hellotime=2s holdtime=7s priority=120 auth="vlan72^@^@"
19:04:02.061482 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [none], proto UDP (17), length 48)

181.173.82.60.1985 > 250.66.33.195.1985: HSRPv0-hello 20: state=standby group=72      addr=171.64.72.1 hellotime=2s holdtime=7s priority=100 auth="vlan72^@^@"
19:04:03.583896 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [none], proto UDP (17), length 48)

181.173.82.61.1985 > 250.66.33.195.1985: HSRPv0-hello 20: state=active group=72  addr=171.64.72.1 hellotime=2s holdtime=7s priority=120 auth="vlan72^@^@"
19:04:04.005483 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [none], proto UDP (17), length 48)
181.173.82.60.1985 > 250.66.33.195.1985: HSRPv0-hello 20: state=standby group=72 addr=171.64.72.1 hellotime=2s holdtime=7s priority=100 auth="vlan72^@^@"
19:04:05.511947 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [none], proto UDP (17), length 48)
181.173.82.61.1985 > 250.66.33.195.1985: HSRPv0-hello 20: state=active group=72 addr=171.64.72.1 hellotime=2s holdtime=7s priority=120 auth="vlan72^@^@"
19:04:05.997361 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [none], proto UDP (17), length 48)

181.173.82.60.1985 > 250.66.33.195.1985: HSRPv0-hello 20: state=standby group=72 addr=171.64.72.1 hellotime=2s holdtime=7s priority=100 auth="vlan72^@^@"
19:04:07.427876 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [none], proto UDP (17), length 48)

181.173.82.61.1985 > 250.66.33.195.1985: HSRPv0-hello 20: state=active group=72 addr=171.64.72.1 hellotime=2s holdtime=7s priority=120 auth="vlan72^@^@"
19:04:07.925385 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [none], proto UDP (17), length 48)

181.173.82.60.1985 > 250.66.33.195.1985: HSRPv0-hello 20: state=standby group=72 addr=171.64.72.1 hellotime=2s holdtime=7s priority=100 auth="vlan72^@^@"
19:04:09.403864 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [none], proto UDP (17), length 48)

181.173.82.61.1985 > 250.66.33.195.1985: HSRPv0-hello 20: state=active group=72 addr=171.64.72.1 hellotime=2s holdtime=7s priority=120 auth="vlan72^@^@"
19:04:09.845241 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [none], proto UDP (17), length 48)

181.173.82.60.1985 > 250.66.33.195.1985: HSRPv0-hello 20: state=standby group=72   addr=171.64.72.1 hellotime=2s holdtime=7s priority=100 auth="vlan72^@^@"
19:04:10.877531 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [none], proto IGMP (2), length 28)

and I want the output be like this:

181.173.82.61
and other ips
(just senders IP (left IP))

I tried the following regular expression in grep:

grep -E -o '[1-9][0-9][0-9]?\.[1-9][0-9][0-9]?\.[0-9][0-9][0-9]?\.[0-9][0-9][0-9]?\.\s\>

To solve this problem I try to check IPs ehit this format:

(ip)(port)(space)(>)

and then sed and delete the > and port numbers but my regular expression dose not work.
I will appreciate any other ways such as awk or better regular expressions.

Arash

Posted 2013-04-23T13:30:19.577

Reputation: 678

Answers

1

If all you want is the first IP of each line, you could do this:

grep '>' file.txt | gawk '{print $1}' | cut -d "." -f -4

Output on your example file:

181.173.82.61
181.173.82.60
181.173.82.61
181.173.82.60
181.173.82.61
181.173.82.60
181.173.82.61
181.173.82.60
181.173.82.61
181.173.82.60

Explanation:

  • grep '>' file.txt : print only those lines that contain the character >. In the file you have posted these are the lines that start with an IP.

    grep '>' file.txt | head -1
    181.173.82.61.1985 > 250.66.33.195.1985: HSRPv0-hello 20: state=active group=72 addr=171.64.72.1 hellotime=2s holdtime=7s priority=120 auth="vlan72^@^@"
    
  • gawk '{print $1}' : print the first field of each line.

      grep '>' file.txt | gawk '{print $1}' | head -1
      181.173.82.61.1985
    
  • cut -d "." -f -4 : use . as the field delimiter and print everything up to the 4th field. This removes the extra numbers from the IPs.

    grep '>' file.txt | gawk '{print $1}' | cut -d "." -f -4 | head -1
    181.173.82.61
    

terdon

Posted 2013-04-23T13:30:19.577

Reputation: 45 216

1

Right now your regular expression is only looking for an IP in the format xxx.xxx.xxx.xxx, but IPs can be x.x.x.x and anything in between like xxx.xxx.x.xx (and in your example: xxx.xxx.xx.xx for the IP portion).

So that means, your regular expression needs to look more like:

'[1-9]{1,3}\.[0-9}{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,4} >'

That says "I want 1-9 anywhere from 1 to 3 in a row, followed by a '.', then 0-9 anywhere from 1-3 in a row", and so-forth. Works for me without ?, FWIW.

Since you are explicitly saying "space and >", you don't need to be overly fancy there.

nerdwaller

Posted 2013-04-23T13:30:19.577

Reputation: 13 366

im not agree with u.it get the ips.(ive tested that) and tnx for your help – Arash – 2013-04-23T16:49:31.537

and your regular expression return 173.82.61.1985 instead of 181.173.82.61.1985 and is not valid ip address – Arash – 2013-04-23T16:56:06.587

1

I am pretty sure it can done better than this, but if I copy your example to a testfile and remove the markup (the extra 4 spaces at the start), then this works:

>cat testfile | grep -E "[1-9]{1,3}\.[0-9}{1,3}\.[0-9]{1,3}\.[1-9]{1,3}" | cut -d. -f1-4

Output of just the grep filters down to:

181.173.82.61.1985 > 250.66.33.195.1985: HSRPv0-hello 20: state=active group=72 addr=171.64.72.1 hellotime=2s holdtime=7s priority=120 auth="vlan72^@^@"
181.173.82.60.1985 > 250.66.33.195.1985: HSRPv0-hello 20: state=standby group=72      addr=171.64.72.1 hellotime=2s holdtime=7s priority=100 auth="vlan72^@^@"
181.173.82.61.1985 > 250.66.33.195.1985: HSRPv0-hello 20: state=active group=72  addr=171.64.72.1 hellotime=2s holdtime=7s priority=120 auth="vlan72^@^@"
181.173.82.60.1985 > 250.66.33.195.1985: HSRPv0-hello 20: state=standby group=72 addr=171.64.72.1 hellotime=2s holdtime=7s priority=100 auth="vlan72^@^@"

Cut is than used to grab only the first four fields (-f for field, 1-4 for 1,2,3,4), using the dot as a -deliminator).

Hennes

Posted 2013-04-23T13:30:19.577

Reputation: 60 739

tnx but its also return some invalid results such as: 181.173.82.60 181.173.82.61 181.173.82.60 181.173.82.61 > 229 181.173.83.239 > 245 181.173.82.61 181.173.82.60 172.30.79.250 > 247 181.173.82.61 181.173.82.60 181.173.82.47 > 245 172.19.11.163 > 253 181.173.82.61 > 239` – Arash – 2013-04-23T16:48:01.310

181.173.82.61 > 229 it means i just want ip not > 229 but your code have few errors and this is nice :) – Arash – 2013-04-23T16:48:35.970

1

Using your example file and a regex, I have come to this simpler solution:

perl -ne 'print "$1\n" if /^(.*)\.\d+ >/' test.txt

It prints every match before ".portnumber >"

Renan

Posted 2013-04-23T13:30:19.577

Reputation: 551

0

I am rather surprised no one posted this extremely simple grep solution. I copied and pasted your sample text into a text file called, "ips.txt" and ran the following command:

grep -Eo "^([0-9]{1,3}\.){3}[^. ]*" ips.txt

The output I got was:

181.173.82.61
181.173.82.60
181.173.82.61
181.173.82.60
181.173.82.61
181.173.82.60
181.173.82.61
181.173.82.60
181.173.82.61
181.173.82.60

And if you want to see ALL the IP_ADDRs in the file, just omit the ^ at the beginning of the regex of the grep command. It will display all IPs in a list for you to further sift through as desired.

enter image description here

Which happens to be the exact same output as the accepted answer only without using so many pipes. So long as your file needing to be parsed contains the sender IP_ADDR at the start of the line, this command will do what you need.

Yokai

Posted 2013-04-23T13:30:19.577

Reputation: 249