1. 概述
在处理日志文件或分析网络流量数据时,我们经常需要从Java的字符串中提取IP地址。
本文将探讨IPv4地址的格式,并利用Java的正则表达式(regex)能力创建解决方案。
2. IP地址基础知识
IPv4地址由四个用点分隔的八位组组成,每个八位组是0到255之间的数字。有效的IPv4地址示例如下:
0.0.0.0
192.168.0.8
234.223.43.42
255.255.255.0
接下来我们将构建一个正则表达式模式,用于识别符合IP地址格式的字符序列。通过应用此模式,我们可以从字符串中提取所有IP地址。
3. 构建匹配IP地址的正则表达式
先看正则表达式,再分析其匹配原理:
(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)[.]){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
该正则使用了非捕获组(?: ),非捕获组用于组合表达式但不创建反向引用。
为便于理解,我们用OCTET_PATTERN
表示八位组模式,正则结构可简化为:
(?:(?:OCTET_PATTERN)[.]){3}(?:OCTET_PATTERN)
这部分匹配前三个({3}
)八位组,后跟字面量点号和第四个八位组。注意:虽然.
在正则中表示任意字符,但放在字符类[.]
中时,它匹配字面量点号。
现在深入分析OCTET_PATTERN
:
(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
这部分通过组合三种可能匹配0到255之间的有效数字,具体分析:
25[0-5]
→ 匹配250-2552[0-4][0-9]
→ 匹配200-249[01]?[0-9][0-9]?
→ 匹配0-199
理解正则原理后,我们创建Java方法来提取IP地址。
4. 实现IP地址提取方法
首先根据正则表达式获取Pattern实例:
static final Pattern IP_PATTERN = Pattern.compile("(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)[.]){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)");
由于字符串可能包含多个IP地址,我们创建一个方法,接受输入字符串并返回提取的IP地址列表:
List<String> extractIP(String input) {
Matcher matcher = IP_PATTERN.matcher(input);
List<String> result = new ArrayList<>();
while (matcher.find()) {
result.add(matcher.group());
}
return result;
}
方法逻辑简单直接:通过matcher.find()
遍历字符串,将每个匹配的子字符串(IP地址)添加到预初始化的ArrayList
中。
接下来创建测试数据验证方法有效性:
场景1:不含IP地址
static final String INPUT1 = "No IP address here";
static final List<String> EXPECTED1 = Collections.emptyList();
场景2:单个有效IP
static final String INPUT2 = "My local ip is 127.0.0.1";
static final List<String> EXPECTED2 = List.of("127.0.0.1");
static final String INPUT3 = "Another ip address is 192.168.42.42";
static final List<String> EXPECTED3 = List.of("192.168.42.42");
场景3:部分有效IP(只提取有效部分)
static final String INPUT4 = "Extract the valid part: 260.1.2.345";
static final List<String> EXPECTED4 = List.of("60.1.2.34");
场景4:完全无效IP
static final String INPUT5 = "No valid ip address 260.42.342.345";
static final List<String> EXPECTED5 = Collections.emptyList();
场景5:多个IP地址
static final String INPUT6 = "We have multiple ip addresses: 127.1.1.0, 192.168.42.42 and 245.30.1.34";
static final List<String> EXPECTED6 = List.of("127.1.1.0", "192.168.42.42", "245.30.1.34");
最后执行测试验证:
assertEquals(EXPECTED1, extractIP(INPUT1));
assertEquals(EXPECTED2, extractIP(INPUT2));
assertEquals(EXPECTED3, extractIP(INPUT3));
assertEquals(EXPECTED4, extractIP(INPUT4));
assertEquals(EXPECTED5, extractIP(INPUT5));
assertEquals(EXPECTED6, extractIP(INPUT6));
测试通过,证明方法有效解决了问题。
5. 总结
本文介绍了如何在Java中从字符串提取IP地址。通过正则表达式创建了检测有效IPv4地址的模式,并基于该模式实现了从给定字符串中捕获所有IP地址的解决方案。
完整示例代码可在GitHub仓库获取。