使用正则表达式匹配文本中的所有IP地址

时间:2018-06-13 08:37:11

标签: ruby regex ipv4

假设我有一个可能包含一个或多个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用空格分隔时,这很有效,例如它从文本192.168.1.1中提取bla bla 192.168.1.1 bla。但是,在这种情况下,它仍会提取192.168.1.1bla bla 192.168.1.1.1.1 bla

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

2 个答案:

答案 0 :(得分:5)

您应该将单词边界匹配器\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"

答案 1 :(得分:4)

如果类似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方法从字符串中收集所有匹配项。