【问题标题】:how to match IPV4 regex pattern by excluding RFC1918 private addresses in python如何通过在python中排除RFC1918私有地址来匹配IPV4正则表达式模式
【发布时间】:2018-06-26 05:29:34
【问题描述】:
import re
text='''10.11.0.0'''

pattern=re.compile(r'(\b(\d|\d{2}|1\d{2}|2[0-5]{2})\.(\d|\d{2}|1\d{2}|2[0-5] 
{2})\.(\d|\d{2}|1\d{2}|2[0-5]{2})\.(\d|\d{2}|1\d{2}|2[0-5]{2})\b)')

#pattern=re.compile(r'\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}\b')
matches=pattern.finditer(text)

for match in matches:
  print(match.group())

这是查找所有 IPV4 地址的正则表达式模式,但我需要排除 RFC1918 地址。请提供建议。

【问题讨论】:

标签: python regex python-2.7


【解决方案1】:

根据this reference,IP地址正则表达式为\b(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}\b

您希望避免匹配以10192.168 开头的 IP 地址以及以172 开头的特定地址范围。

使用

\b(?!10\.|192\.168\.|172\.(?:1[6-9]|2[0-9]|3[01])\.)(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}\b

regex demo

详情

  • \b - 字边界
  • (?!10\.|192\.168\.|172\.(?:1[6-9]|2[0-9]|3[01])\.) - 如果接下来出现 RFC1918 地址“标记”,则 否定前瞻 匹配失败:
    • 10\. - 10.
    • 192\.168\. - 192.168.
    • 172\.(?:1[6-9]|2[0-9]|3[01])\. - 172.,然后是 16 到 31 和 .
  • (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?) - 八位字节正则表达式(注意非捕获组,您可以将此模式与 re.findall 一起使用以方便地返回所有匹配项,无需使用 re.finditer 迭代匹配项)
  • (?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3} - 一个点重复 3 次,后面跟着一个八位字节
  • \b - 字边界

Python demo:

import re
octet = r'(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'
pattern=re.compile(r"\b(?!10\.|192\.168\.|172\.(?:1[6-9]|2[0-9]|3[01])\.){0}(?:\.{0}){{3}}\b".format(octet))
text = "10.11.0.0 and here are 192.168.0.0 and 192.168.0.2 145.12.24.45"
print(pattern.findall(text)) # => ['145.12.24.45']

【讨论】:

    【解决方案2】:

    此正则表达式匹配 RFC1918 中的地址:

    (^192\.168\.([0-9]|[0-9][0-9]|[0-2][0-5][0-5])\.([0-9]|[0-9][0-9]|[0-2][0-5][0-5])$)|(^172\.([1][6-9]|[2][0-9]|[3][0-1])\.([0-9]|[0-9][0-9]|[0-2][0-5][0-5])\.([0-9]|[0-9][0-9]|[0-2][0-5][0-5])$)|(^10\.([0-9]|[0-9][0-9]|[0-2][0-5][0-5])\.([0-9]|[0-9][0-9]|[0-2][0-5][0-5])\.([0-9]|[0-9][0-9]|[0-2][0-5][0-5])$)
    

    在这里找到:https://www.regextester.com/95489

    要达到预期的结果,只需匹配所有 IP,然后删除与您要排除的 IP 匹配的那些(保持接近您自己的示例):

    import re
    text='''10.11.0.0', 192.168.1.1, 123.4.5.6'''
    
    pattern=re.compile(r'(\b(\d|\d{2}|1\d{2}|2[0-5]{2})\.(\d|\d{2}|1\d{2}|2[0-5]{2})\.(\d|\d{2}|1\d{2}|2[0-5]{2})\.(\d|\d{2}|1\d{2}|2[0-5]{2})\b)')
    exclude=re.compile(r'(^192\.168\.([0-9]|[0-9][0-9]|[0-2][0-5][0-5])\.([0-9]|[0-9][0-9]|[0-2][0-5][0-5])$)|(^172\.([1][6-9]|[2][0-9]|[3][0-1])\.([0-9]|[0-9][0-9]|[0-2][0-5][0-5])\.([0-9]|[0-9][0-9]|[0-2][0-5][0-5])$)|(^10\.([0-9]|[0-9][0-9]|[0-2][0-5][0-5])\.([0-9]|[0-9][0-9]|[0-2][0-5][0-5])\.([0-9]|[0-9][0-9]|[0-2][0-5][0-5])$)')
    
    matches = pattern.finditer(text)
    filtered = [match.group() for match in matches if not exclude.match(match.group())]
    
    for match in filtered:
      print(match)
    

    请注意,如果您希望列表很大,也可以使用生成器推导而不是列表推导来获得相同的结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-31
      • 1970-01-01
      • 2022-12-11
      • 1970-01-01
      • 2011-03-01
      相关资源
      最近更新 更多