使用正则表达式匹配文本中的所有 IP 地址
Match all IP addresses in text with regex
假设我有一个字符串,其中可能包含一个或多个 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.1
:bla bla 192.168.1.1.1.1 bla
。
如何让它不匹配这种情况?即当它是 192.168.1.1.1.1
时,我的正则表达式不应该 return 匹配。我已经寻找了很多关于这个问题的解决方案,但找不到我想要的。我也试图通过最后只匹配空格来自己找出解决方案(因为 \b
也匹配 .
字符)但我无法使其工作。
谢谢
您应该将单词边界匹配器 \b
更改为显式 space(并使用正前瞻匹配它,因为您不希望它被返回):
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"
如果类 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
方法从字符串中收集所有匹配项。
假设我有一个字符串,其中可能包含一个或多个 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.1
:bla bla 192.168.1.1.1.1 bla
。
如何让它不匹配这种情况?即当它是 192.168.1.1.1.1
时,我的正则表达式不应该 return 匹配。我已经寻找了很多关于这个问题的解决方案,但找不到我想要的。我也试图通过最后只匹配空格来自己找出解决方案(因为 \b
也匹配 .
字符)但我无法使其工作。
谢谢
您应该将单词边界匹配器 \b
更改为显式 space(并使用正前瞻匹配它,因为您不希望它被返回):
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"
如果类 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
方法从字符串中收集所有匹配项。