【问题标题】:Match all IP addresses in text with regex将文本中的所有 IP 地址与正则表达式匹配
【发布时间】:2018-11-22 18:23:24
【问题描述】:

假设我有一个可能包含一个或多个 IP 地址的字符串。如何在 ruby​​ 中使用正则表达式匹配所有这些并且只匹配有效的?

目前,我的解决方案如下所示:

IP_ADDR_REGEX = %r{
  \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]?)\.
  (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]?)
  \b
}x

这在 IP 用空格分隔时效果很好,例如它从文本 bla bla 192.168.1.1 bla 中提取 192.168.1.1。但是,在这种情况下,它仍会提取 192.168.1.1bla bla 192.168.1.1.1.1 bla

如何使它不匹配这种情况?即当它是 192.168.1.1.1.1 时,我的正则表达式不应该返回匹配项。我已经寻找了很多关于这个问题的解决方案,但找不到我想要的。我还尝试通过最后仅匹配空格来自己找出解决方案(因为\b 也匹配. 字符)但我无法使其工作。 谢谢

【问题讨论】:

  • 只是 IPv4 地址?
  • 请注意[a:b:c::d:e:f]也是一个有效的IP地址,例如[::]

标签: ruby regex ipv4


【解决方案1】:

您应该将单词边界匹配器 \b 更改为显式空格(并使用正向前瞻匹配它,因为您不希望它被返回):

IP_ADDR_REGEX = %r{
  (?<=\s|^)
  (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]?)\.
  (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]?)
  (?=\s|$)
}x

main ▶ 'bla bla 192.168.1.1.1.1 bla'[IP_ADDR_REGEX]
#⇒ nil
main ▶ 'bla bla 192.168.1.1.1 bla'[IP_ADDR_REGEX]
#⇒ nil
main ▶ 'bla bla 192.168.1.1 bla'[IP_ADDR_REGEX]
#⇒ "192.168.1.1"

【讨论】:

    【解决方案2】:

    如果类似 IP 的字符串前面有一个数字和一个点,或者后面有一个点和一个数字,您可以通过添加查找失败来解决它:

    IP_ADDR_REGEX = %r{
      \b                                        # Word boundary
      (?<!\d\.)                                 # Negative lookbehind: no "X." before
      (?: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]?)\.
      (?: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]?)
      \b                                        # Word boundary
      (?!\.\d)                                  # Negative lookahead: no ".X" after
    }x
    

    Regex demo #1

    请注意,如果您只想将匹配限制为以空格分隔的子字符串,请使用

    IP_ADDR_REGEX = %r{
      (?<!\S)                                    # Position not preceded with non-whitespace char
      (?: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]?)\.
      (?: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]?)
      (?!\S)                                    # Position not followed with non-whitespace char
    }x
    

    Regex demo #2

    请注意,(?:...) 非捕获组可以更轻松地使用 String#scan 方法从字符串中收集所有匹配项。

    【讨论】:

      猜你喜欢
      • 2011-05-12
      • 2022-12-07
      • 1970-01-01
      • 2012-04-27
      • 2011-08-17
      • 2011-08-27
      • 2012-05-17
      • 2011-03-01
      • 1970-01-01
      相关资源
      最近更新 更多