【问题标题】:How can I find an IP address in a long string with REGEX?如何使用 REGEX 在长字符串中找到 IP 地址?
【发布时间】:2021-04-08 14:34:59
【问题描述】:

我想了解如何从很长的字符串中仅提取正确 IP 地址。 问题是我的代码提取了 IP 地址,即使它的一部分有超过 3 位数字(这是不正确的)。

我尝试了解有关 Python REGEX 的更多信息,但我不知道如何在点后最多连续 3 个数字处停止它。 我的意思是,如果 IP 是 1.2.3.4,它会正确找到它,这确实是正确的,但如果 IP 是 1.2.3.4567,它也会正确找到它,这是不正确的。我不知道如何对它说,如果一个组的位数超过 3 位,那就不是 IP 地址。

import re

secv = "akmfiawnmgisa gisamgisamgsagr[sao l321r1m r2p4 2342po4k2m4 22.33.4.aer 1.2.3.5344 99.99.99.100 asoifinagf sadgsangidsng sg"

b = re.findall(r"[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.\d{1,3}", secv)

print(b)

它打印1.2.3.534499.99.99.100,但1.2.3.5344 不是IP 地址,因为它有3 个以上的连续数字。

【问题讨论】:

  • 您只需要一些边界,例如 $ 或 \s,\b 来包装有效 IP:\b[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.\d{1,3}\b
  • 它确实打印 1.2.3.5344。但是它会打印 1.2.3.534,这是您的正则表达式的有效表达式(但不是有效的 IP 地址,因为它高于 255)。问题是它后面跟着另一个数字。您可以使用前瞻并要求下一个字符 not 是数字,以避免找到 1.2.3.534 如果这是您想要的。
  • 谢谢,IWHKYB!有效。但是 JohanL,我如何检查下一个字符是否是数字?

标签: python python-3.x regex


【解决方案1】:
import re

secv = "90.123.1.100 akmfiawnmgisa gisamgisamgsagr[sao l321r1m r2p4 2342po4k2m4 22.33.4.aer 1.2.3.5344 99.99.99.100 asoifinagf sadgsangidsng sg 13.18.19.100 1.2.3.4"

b = re.findall(r"(?:\s|\A)(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?=\s|\Z)",secv)

b = list(filter(lambda x: all([int(y) <= 255 for y in x.split('.')]), b))


print(b)

为了让它更有趣,我在字符串的开头和结尾添加了 IP 地址。我假设如果 IP 地址不在字符串的开头或结尾,则需要在两边用空格分隔。所以我在 REGEX 的开头添加了一个非捕获组 (?:\s|\A) ,它将匹配空格字符 的开头细绳。我还在 REGEX 的末尾添加了一个 lookahead assertion (?=\s|\Z),它将匹配单个空格字符或行尾 而不消耗任何字符。以上打印出来:

['90.123.1.100', '99.99.99.100', '13.18.19.100', '1.2.3.4']

【讨论】:

  • 这不是 IP 地址的有效正则表达式。例如。它将匹配999.999.999.999...
  • @R2RT 确实如此。如果您查看 完全 有效 IP 的 REGEX,它会相当冗长。这个问题的重点主要是确保您不会无意中得到最后一个 4 位数的组件。因此,我提供的重点是测试所需字符串所在的上下文。另一种处理更彻底测试的方法是在运行上述 REGEX 之后,然后通过将每个结果拆分为 '.' 来过滤结果。字符并确保每个组件为 255 或更少(或任何规则)。
  • @R2RT 我已经回去添加了这样一个过滤器。
  • 问题的重点是“仅从很长的字符串中提取正确的 IP 地址”。 SO 应该是关于好问题的好答案的存储库,而不仅仅是当前 OP 问题的解决方案。即使您帮助了 OP,他可能会感到满意,但其他读者可能不会。如果您考虑到这一点,我会投票赞成。
  • @R2RT 我相信现在的解决方案可以做到这一点。它不必全部由 REGEX 完成——这不是要求。 C++ 语言是上下文敏感的,但使用依赖语义处理(例如使用符号表)的上下文无关语法来解析,以确定输入的程序是否有效。
【解决方案2】:

只需搜索出现 4 次的模式 [1-2]?[0-9]{1,2},以点分隔。可选择在开头和结尾使用单词边界锚定您的正则表达式模式

>>> re.findall(r'\b(?:[1-2]?[0-9]{1,2}\.){3}[1-2]?[0-9]{1,2}\b', secv)
['99.99.99.100']                                                      

【讨论】:

  • 它有效,但它也将 IP 地址视为 */12.12.12.12 之类的序列,这些字符在 12 之前。所以我做了什么,我把“+”放在开头和结尾seq 检查 IP 地址是否被空格包围。
猜你喜欢
  • 2016-09-20
  • 2019-08-25
  • 2012-02-17
  • 2020-11-22
  • 2012-07-03
  • 1970-01-01
  • 2012-07-01
  • 2013-05-25
  • 2012-05-18
相关资源
最近更新 更多