How to match IP addresses in a comma-separated string

Viewed 148

Code show as below, but there is a problem: "255.255.255.256" will be processed into "255.255.255.25"

import re

ip_pattern = re.compile(r"((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)")

def get_ip_by_regex(ip_str):
    """Match IP from the given text and return

    :param ip_str: like "255.255.255.255,255.255.255.256,260.255.255.255"
    :type ip_str: string
    :return: IP LIST ["255.255.255.255"]
    :rtype: list[string]
    """
    ret = []
    for match in ip_pattern.finditer(ip_str):
        ret.append(match.group())
    return ret

If I pass the 255.255.255.255,255.255.255.256,260.255.255.255 string I expect ["255.255.255.255"] as the results.

3 Answers

You want to implement comma boundaries, (?<![^,]) and (?![^,]):

ip_pattern = re.compile(r"(?<![^,])(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)(?![^,])")

See the regex demo.

Details

  • (?<![^,]) - a negative lookbehind that matches a location not immediately preceded with a char other than a comma (i.e. there must be a comma or start of string immediately to the left of the current location)
  • (?![^,]) - a negative lookahead that matches a location not immediately followed with a char other than a comma (i.e. there must be a comma or end of string immediately to the right of the current location).

See the Python demo:

import re

ip_pattern = re.compile(r"(?<![^,])(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)(?![^,])")

def get_ip_by_regex(ip_str):
    """Match IP from the given text and return

    :param ip_str: like "255.255.255.255,255.255.255.256,260.255.255.255"
    :type ip_str: string
    :return: IP LIST ["255.255.255.255"]
    :rtype: list[string]
    """
    return ip_pattern.findall(ip_str)

print(get_ip_by_regex('255.255.255.255,255.255.255.256,260.255.255.255'))
# => ['255.255.255.255']

You forgot splitting. To avoid overlapping, I suggest split first. Then you can match or finditer. Here's correct IP pattern with finding logic:

r"(([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])"


def get_ip_by_regex(ip_str):
    """Match IP from the given text and return

    :param ip_str: like "255.255.255.255,255.255.255.256,260.255.255.255"
    :type ip_str: string
    :return: IP LIST ["255.255.255.255"]
    :rtype: list[string]
    """
    ret = []
    for p in ip_str.split(','):
        for match in ip_pattern.finditer(ip_str):
            ret.append(match.group())
    return ret

With word boundaries:

import re

ip_pattern = re.compile(r"\b((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)\b")

def get_ip_by_regex(ip_str):
    """Match IP from the given text and return

    :param ip_str: like "255.255.255.255,255.255.255.256,260.255.255.255"
    :type ip_str: string
    :return: IP LIST ["255.255.255.255"]
    :rtype: list[string]
    """
    ret = []
    for match in ip_pattern.finditer(ip_str):
        ret.append(match.group())
    return ret

print(get_ip_by_regex("255.255.255.255,255.255.255.256,260.255.255.255"))

Python code

Related