Question: I have the following patterns (each example is in a different file): example one ----------- alpha: 192.168.50.0 - 192.168.50.24 delta: 192.168.50.100 - 192.168.50.124 other fields: more stuff .... example two ------------- gamma: 200.0.0.0 - 200.0.0.64 lamda: 200.0.0.124 - 200.0.0.255 other fields: more stuff ....  I'm using Python to iterate the files, and I'm trying to find a one liner to match only 'alpha' or 'gamma' occurrences, and only the second ip in the range. So in our examples it will be: 192.168.50.24 or 200.0.0.64 Something like, that will give me only the second ip: (?<=alpha:\s)|(?<=gamma:\s).* 

Answer: I'd always lean on the excellent ipaddress library whenever dealing with IP addresses because of its easy validity checking (use a simpler regex and just try it), comparison methods (ip in network?), support for IPv4 and IPv6, and understanding of special ranges (global, link_local, multicast..) - additionally, you may consider a custom class for managing these ranges If you eventually want the complete ranges and are working around it by just finding the second, something like this may more clearly get what you're after and be useful to build with (note you can match if instance.label: in a script) class IPRange: def __init__(self, line=None, *, label=None, start=None, end=None): if line and (start or end): raise TypeError("only a line or start+end are expected") # adjust regex if IPv6 is needed # or I'd suggest `.split(":", 1)` and `.split(" - ")` again if line: # pull start and end from line match = re.match(r"^([^:]+):\s*([\d\.]{7,15})\s-\s([\d\.]{7,15})$", line) if not match: raise ValueError(f"not a valid line: {line}") _label, start, end = match.groups() label = label or _label # allow setting label self.label = label # allow None # ValueError if either is not an IP Address self.ip_start = ipaddress.ip_address(start) self.ip_end = ipaddress.ip_address(end) if self.ip_start > self.ip_end: # NOTE allows == raise ValueError(f"start must be before end: cmp({self.ip_start} > {self.ip_end})") # opportunity to reject special/reserved addresses or ranges def __repr__(self): return f"{type(self).__name__}({self.label}, {self.ip_start}, {self.ip_end})" def __contains__(self, other): """ support checking `ip in IPRange` """ other = ipaddress.ip_address(other) # opportunity to reject special/reserved addresses or ranges return self.ip_start <= other <= self.ip_end  Example Usage >>> r = IPRange("alpha: 192.168.50.0 - 192.168.50.24") >>> "192.168.50.1" in r True >>> "192.168.50.25" in r False >>> print(IPRange(label="foo", start="127.0.0.3", end="127.0.0.5")) IPRange(foo, 127.0.0.3, 127.0.0.5) >>> print(IPRange(label="foo", start="127.0.0.3", end="127.0.0.2")) [..] ValueError: start must be before end: cmp(127.0.0.3 > 127.0.0.2)  Chewing on multiple lines for line in data.splitlines(): try: print(IPRange(line)) except ValueError as ex: print(f"failed: {repr(ex)}")  failed: ValueError('not a valid line: example one') failed: ValueError('not a valid line: -----------') failed: ValueError('None does not appear to be an IPv4 or IPv6 address') IPRange(alpha, 192.168.50.0, 192.168.50.24) IPRange(delta, 192.168.50.100, 192.168.50.124) failed: ValueError('not a valid line: other fields: more stuff') failed: ValueError('not a valid line: ....') failed: ValueError('None does not appear to be an IPv4 or IPv6 address') failed: ValueError('not a valid line: example two') failed: ValueError('not a valid line: -------------') failed: ValueError('None does not appear to be an IPv4 or IPv6 address') IPRange(gamma, 200.0.0.0, 200.0.0.64) IPRange(lamda, 200.0.0.124, 200.0.0.255) failed: ValueError('not a valid line: other fields: more stuff') failed: ValueError('not a valid line: ....')  Also take a look at ipaddress.summarize_address_range(start, end) which might be a useful iterator (__iter__ method?) too