21

In the following ip address validation i want to see if it a valid ip address or not how can i do this using the below re

>>> ip="241.1.1.112343434" 
>>> aa=re.match(r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}[^0-9]",ip)
>>> aa.group()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'
Rajeev
  • 44,985
  • 76
  • 186
  • 285
  • 3
    regex is a crappy way to check ip addresses. you have to match numbers up to 255, but not 256, so the regex to do this properly is rather large – John La Rooy Apr 10 '12 at 10:03

5 Answers5

42

Why not use a library function to validate the ip address?

>>> ip="241.1.1.112343434" 
>>> socket.inet_aton(ip)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
socket.error: illegal IP address string passed to inet_aton
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
  • 2
    Only one thing here. If you use this approach 1 also will be suitable ip address according man page. – Khamidulla Jul 27 '15 at 05:35
  • 3
    @Phoenix, yes `1` is equivalent to `0.0.0.1` (as it should be). This is why you should prefer specialised library functions to regex hacks. – John La Rooy Jul 27 '15 at 06:41
  • This is the best approach IMO. Regex hacks are always prone to errors and using a builtin for such validations should be the first choice. – 7h3rAm May 21 '18 at 21:12
  • 2
    Old answer but still relevant, I would argue that this is not a perfect approach, considering the use case where OP needs to ensure that the original string needs to be in the form XXX.XXX.XXX.XXXXX. Using the socket.inet_aton would allow an ip of "1", which as mentioned above by @JohnLaRooy is indeed a valid IP address, but it may not be valid where the string must contain 4 octets and a port (which is a requirement unspecified by OP). In this case, I would consider using a combination of socket.inet_aton and the regex approachs – spencer Oct 31 '18 at 14:38
38

Use anchors instead:

aa=re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$",ip)

These make sure that the start and end of the string are matched at the start and end of the regex. (well, technically, you don't need the starting ^ anchor because it's implicit in the .match() method).

Then, check if the regex did in fact match before trying to access its results:

if aa:
    ip = aa.group()

Of course, this is not a good approach for validating IP addresses (check out gnibbler's answer for a proper method). However, regexes can be useful for detecting IP addresses in a larger string:

ip_candidates = re.findall(r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b", ip)

Here, the \b word boundary anchors make sure that the digits don't exceed 3 for each segment.

Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
  • 12
    It would be failed on `111.111.111.345` that is outside the range of ip addresses. – Root May 25 '17 at 08:49
  • import re def is_valid_ip(ip): ipv = re.match(r"^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$",ip) return bool(ipv) and all(map(lambda n: 0<=int(n)<=255, ipv.groups())) ip = input("Enter the ip address for validation:") print (is_valid_ip(ip)) – Diwakar SHARMA May 11 '19 at 20:59
22

\d{1,3} will match numbers like 00 or 333 as well which wouldn't be a valid ID.

This is an excellent answer from smink, citing:

ValidIpAddressRegex = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$";
Community
  • 1
  • 1
Llamageddon
  • 3,306
  • 4
  • 25
  • 44
17
try:
    parts = ip.split('.')
    return len(parts) == 4 and all(0 <= int(part) < 256 for part in parts)
except ValueError:
    return False # one of the 'parts' not convertible to integer
except (AttributeError, TypeError):
    return False # `ip` isn't even a string
Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
  • This is better in my case. Thank you. – Khamidulla Jul 27 '15 at 05:48
  • 3
    If you're going for even stricter validation, I'd replace the validation for `return len(parts) == 4 and all(0 < len(part) < 4 and 0 <= int(part) < 256 for part in parts)`, just in case we encounter a string like this: `1.1.00000000003.1`. – LuissRicardo Sep 13 '19 at 02:15
  • @LuissRicardo In what instance would an ip address look like that? Or even be returned in that format? – Joshua Rose Jul 01 '20 at 23:27
  • 2
    The point is exactly to make sure that we weren't given something that *isn't* an IP address. – Karl Knechtel Jul 02 '20 at 02:57
5

The following will check whether an IP is valid or not: If the IP is within 0.0.0.0 to 255.255.255.255, then the output will be true, otherwise it will be false:

[0<=int(x)<256 for x in re.split('\.',re.match(r'^\d+\.\d+\.\d+\.\d+$',your_ip).group(0))].count(True)==4

Example:

your_ip = "10.10.10.10"
[0<=int(x)<256 for x in re.split('\.',re.match(r'^\d+\.\d+\.\d+\.\d+$',your_ip).group(0))].count(True)==4

Output:

>>> your_ip = "10.10.10.10"
>>> [0<=int(x)<256 for x in re.split('\.',re.match(r'^\d+\.\d+\.\d+\.\d+$',your_ip).group(0))].count(True)==4
True
>>> your_ip = "10.10.10.256"
>>> [0<=int(x)<256 for x in re.split('\.',re.match(r'^\d+\.\d+\.\d+\.\d+$',your_ip).group(0))].count(True)==4
False
>>>
Ranga
  • 113
  • 3
  • 9
  • Have you really run this code to show output? I doubt as `your-ip` is an invalid variable name. Also I see this answer has been put very lately, but the other answers are much more readable. – 0xc0de Apr 29 '16 at 08:31
  • its a typo mistake would have put '_' instead. yes had run the code and got correct output. let me know if any thing wrong – Ranga May 08 '17 at 10:04
  • The point was- A piece of code was posted with a typo, which can not be executed yet output is shown. If you want to show output, please make sure you post the same code that's executed, not anything else. – 0xc0de May 08 '17 at 10:37
  • yes Posted the executed code. Thanks for pointing out. – Ranga May 08 '17 at 10:46
  • 1
    this would match something like 0.00004.00009.0123 – Fabio Jul 23 '23 at 19:46