Regex仅匹配范围中的第二个ip地址

63lcw9qa  于 12个月前  发布在  其他
关注(0)|答案(5)|浏览(122)

我试图只匹配第二个有效的ip地址在一个字符串与范围的ip地址。有时候地址之间没有空格,有时候有一个或多个空格。有时候IP无效,所以不应该匹配。

test = '''
1.0.0.0-1.0.0.240
2.0.0.0 - 1.0.0.241
3.0.0.0 -1.0.0.242
4.0.0.0- 1.0.0.243
5.0.0.0  -  1.0.0.244
6.0.0.0 -  1.0.0.245
7.0.0.0 -  1.0.0.2456 #NOT VALID SO DONT MATCH
'''

pattern = r"(?<=-\s))\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
r = re.compile(pattern, re.DOTALL)
print(r.findall(test))

我的尝试只抓到:和1.0.0.2411.0.0.243

wlzqhblo

wlzqhblo1#

将regex模式更改为以下内容:

pattern = r"(?<=[-\s])((?:\d{1,3}\.){3}\d{1,3})$"
r = re.compile(pattern, re.M)
print(r.findall(test))
  • (?<=[-\s])- lookbehindAssert,用于匹配-\s作为IP地址之前的边界(在您的情况下这就足够了)
  • (?:\d{1,3}\.){3}-匹配前3个八位字节,每个八位字节后接IP地址的.
  • $-匹配多行文本中字符串的结尾(由re.M识别)
['1.0.0.240', '1.0.0.241', '1.0.0.242', '1.0.0.243', '1.0.0.244', '1.0.0.245']
ngynwnxp

ngynwnxp2#

所有4个现有的答案都是关于正则表达式的,所以我想你可能会发现第五个使用内置库的答案很有趣:重新发明轮子是没有意义的,特别是当预制的轮子在你的手臂的范围内。
-分割每一行,然后尝试解析后面的部分。如果有ValueError,我们跳过。否则,将其添加到列表中并继续:

from ipaddress import IPv4Address

def get_last_of_ranges_from_text(text):
  lines = text.strip().splitlines()
  last_of_ranges = []
    
  for line in lines:
    _, last = line.split('-')
    
    try:
      last_ip = IPv4Address(last.strip())
    except ValueError:
      pass
    else:
      last_of_ranges.append(last_ip)

  return last_of_ranges

关于以下案文:

1.0.0.0-1.0.0.240
2.0.0.0 - 1.0.0.241
3.0.0.0 -1.0.0.242
4.0.0.0- 1.0.0.243
5.0.0.0  -  1.0.0.244
6.0.0.0 -  1.0.0.245
7.0.0.0 -  1.0.0.2456

.它输出:

[
  IPv4Address('1.0.0.240'), IPv4Address('1.0.0.241'), IPv4Address('1.0.0.242'),
  IPv4Address('1.0.0.243'), IPv4Address('1.0.0.244'), IPv4Address('1.0.0.245')
]

很棒,不是吗?作为奖励,这些IPv4Address es还支持比较运算符:

first_ip < last_ip

我相信你知道该怎么处理它们。

vaqhlq81

vaqhlq813#

这应该与您的所有示例相匹配:

pattern = r"^.*\s*-\s*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$"
r = re.compile(pattern)
print(r.findall(test))

您也可以使用group函数获取第二个IP。

oymdgrw7

oymdgrw74#

假设您可以在第二个IP之后有其他文本(而不仅仅是行尾),您可以更改最后一部分以添加连续4位的负前瞻。要获取第二个IP,您的方法似乎是基于存在空格和破折号的字符串,因此您可以对IP地址之前的其中一个字符串使用lookbehind:

(?<=[ -])(?:\d{1,3}\.){3}(?!\d{4})\d{1,3}
4xrmg8kj

4xrmg8kj5#

test = '''
1.0.0.0-1.0.0.240
2.0.0.0 - 1.0.0.241
3.0.0.0 -1.0.0.242
4.0.0.0- 1.0.0.243
5.0.0.0  -  1.0.0.244
6.0.0.0 -  1.0.0.245
7.0.0.0 -  1.0.0.2456 #NOT VALID SO DONT MATCH
'''

pattern = r"(?<=-\s))\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
r = re.compile(pattern, re.DOTALL)
print(r.findall(test))

零长度Assert需要两个字符:破折号后跟空格字符,您的示例建议您需要破折号或空格字符,这些字符可能另外表示为-|,以避免使用误报字边界\b

import re
...
found = re.findall(r"(?<=-| )\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b", test)
print(found)

给出输出

['1.0.0.240', '1.0.0.241', '1.0.0.242', '1.0.0.243', '1.0.0.244', '1.0.0.245']

相关问题