0

With an IPv4 address range like 169.254.0.0/16 or 192.168.0.0/16, it is straightforward to construct a regex for each, since once you exactly match the first 6 digits, you're done.

But what about matching any address in a looser reserved range such as

100.64.0.0 –
100.127.255.255

A regex beginning with 100\. won't suffice, because there will be numbers outside of the 100.64 and 100.127 bounds (e.g. 100.65.0.0, 100.127.255.256) that will be erroneously matched. How best to capture a range such as this without having to explicitly define each and every valid subrange within each range? The language is Python.

For reference, a full list of reserved IP addresses and ranges can be found here.

Pyderman
  • 14,809
  • 13
  • 61
  • 106
  • dupe? http://stackoverflow.com/questions/106179/regular-expression-to-match-dns-hostname-or-ip-address – Avinash Raj Jun 23 '15 at 05:08
  • 3
    Why don't you use an IP address library? https://docs.python.org/3/library/ipaddress.html or https://pypi.python.org/pypi/py2-ipaddress/ – TessellatingHeckler Jun 23 '15 at 05:08
  • @TessellatingHeckler because ipaddress.ip_address will only tell me that an address is valid. It does not help me detect reserved IP addresses. – Pyderman Jun 23 '15 at 05:12
  • @AvinashRaj Nope, not a dupe. I already have a regex that matches all IP addresses. We need a regex that matches only subsets. – Pyderman Jun 23 '15 at 05:14
  • 1
    @Pyderman yes it does. `try: addr = IPv4Address(text); except ValueError: print("not a valid IP address")` `if addr in IPv4Network('100.64.0.0/10'): print("that's a reserved address")` – TessellatingHeckler Jun 23 '15 at 05:15
  • @TessellatingHeckler 100.64.0.0/10 is the address block. An actual example would be 10.64.1.1, in which case ipaddress.IPv4Address() just tells me that it's valid. – Pyderman Jun 23 '15 at 05:20
  • 1
    @Pyderman You're missing the wonders of Python container types. "address in network". Try `IPv4Address('100.64.1.1') in IPv4Network('100.64.0.0/10')` and it will say True. Try `IPv4Address('100.63.1.1') in IPv4Network('100.64.0.0/10')` and it's False – TessellatingHeckler Jun 23 '15 at 05:34
  • there must be a space before and after the ip addresses right? – Joe T. Boka Jun 23 '15 at 05:45
  • @TessellatingHeckler Ah OK. I wasn't aware that the ipaddress module *knows* about these reserved ranges. So it's safe enough then to put all the ranges (address blocks) on that Wiki page into a list, and then for any given IP address found, test if IPv4Address(theIP) in IPv4Network(blocks[i]) and so on? – Pyderman Jun 23 '15 at 05:59
  • @Pyderman Yeah, I think so. – TessellatingHeckler Jun 23 '15 at 06:04
  • @TessellatingHeckler Thanks. Works well in the interpreter, yet when I put it into a functions, I encounter this problem: http://stackoverflow.com/questions/30996380/python-ipaddress-attributeerror-str-object-has-no-attribute – Pyderman Jun 23 '15 at 07:26

2 Answers2

3

Use of an IPv4 parsing library is preferred. If you insist in using regular expression,

re.search('^(100\.(6[4-9]|[7-9]\d|1[0-1]\d|12[0-7])(\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])){2})$', text)

You can see that I am searching separately for:

  • 64-69 (6[4-9])
  • 70-99 ([7-9]\d)
  • 100-119 (1[0-1]\d)
  • 120-127 (12[0-7])

and

  • 0-9 (\d)
  • 10-99 ([1-9]\d)
  • 100-199 (1\d\d)
  • 200-249 (2[0-4]\d)
  • 250-255 (25[0-5])
Alan Tam
  • 2,027
  • 1
  • 20
  • 33
0

This is one way to do it:

import re

print re.findall(r'\d+\.\S+\d', 'fdgsdfg 100.127.255.255 ggffgsdf 100.64.0.0 asdffsdf')

Output:

['100.127.255.255', '100.64.0.0']
Joe T. Boka
  • 6,554
  • 6
  • 29
  • 48
  • 1
    That doesn't answer if 100.127.255.255 is in the 100.64.0.0/10 subnet or not. – TessellatingHeckler Jun 23 '15 at 06:53
  • @TessellatingHeckler what do you mean? – Joe T. Boka Jun 23 '15 at 06:58
  • 1
    I mean the question is not asking about pulling an IP address out of a line of text, which is what you are doing. The question is asking about comparing one IP address to see if it is between two others. It's the difference between "pulling a number out of a line of text" and "seeing if a number is between 5 and 15". IP addresses and networks have a tree structure. `10.0.5.0/24` is *in* `10.0.0.0/16` and it is also *in* `8.0.0.0/6`, and it is within the range `10.0.4.0-10.0.8.254`. It is this kind of test that the question was asking for - something which works with the way IPs work. – TessellatingHeckler Jun 23 '15 at 07:37