
在处理日志文件、配置文件或特定格式的文本数据时,我们经常需要从中提取结构化的信息。一个常见的挑战是,目标数据可能以可变数量的重复模式出现,例如,一个记录可能包含一个或多个日期-数值对。直接使用正则表达式尝试一次性捕获所有这些可变数量的组往往会导致正则表达式过于复杂、难以维护,甚至无法正确匹配所有情况。
例如,考虑以下数据片段,我们希望从中提取与特定标识符(如 /Jack/M)关联的区段编号、日期和数值:
#Section250342,Main,First/HS/12345/Jack/M,200010 10.00 200011 -2.00, #Section250322,Main,First/HS/12345/Aaron/N,200010 17.00, #Section250399,Main,First/HS/12345/Jimmy/N,200010 12.00, #Section251234,Main,First/HS/12345/Jack/M,200011 11.00
我们的目标是:
关键在于,日期和数值总是成对出现,但每行中这样的对可能有一个或多个。一个常见的错误尝试是编写一个包含多个可选捕获组的复杂正则表达式,但这通常会导致捕获组数量不固定,且难以正确处理所有情况。
解决这类问题的有效策略是:
立即学习“Java免费学习笔记(深入)”;
我们设计一个正则表达式,它将捕获两个主要组:
#Section(d+)(?:(?!#Sectiond).)*Jack/M,(d+h+[-+]?d+(?:.d+)?(?:s+d+h+[-+]?d+(?:.d+)?)*)
下面是对这个正则表达式的详细解释:
使用Java的 Pattern 和 Matcher 类来执行正则表达式匹配,并对捕获到的第二个组进行进一步处理。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DataExtractor {
public static void main(String[] args) {
String regex = "#Section(\d+)\b(?:(?!#Section\d).)*\bJack/M,(\d+\h+[-+]?\d+(?:\.\d+)?(?:\s+\d+\h+[-+]?\d+(?:\.\d+)?)*)";
String string = "#Section250342,Main,First/HS/12345/Jack/M,200010 10.00 200011 -2.00,
"
+ "#Section250322,Main,First/HS/12345/Aaron/N,200010 17.00,
"
+ "#Section250399,Main,First/HS/12345/Jimmy/N,200010 12.00,
"
+ "#Section251234,Main,First/HS/12345/Jack/M,200011 11.00";
Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE); // 启用多行模式
Matcher matcher = pattern.matcher(string);
System.out.println("--- 逐条匹配结果 ---");
while (matcher.find()) {
List<String> dates = new ArrayList<>();
List<String> values = new ArrayList<>();
// 提取第一个捕获组:区段编号
System.out.println("区段编号 (Group 1): " + matcher.group(1));
// 提取第二个捕获组:所有日期和数值的组合字符串
String[] parts = matcher.group(2).split("\s+"); // 按一个或多个空白字符分割
// 对分割后的字符串进行后处理,分离日期和数值
for (int i = 0; i < parts.length; i++) {
if (i % 2 == 0) { // 偶数索引是日期
dates.add(parts[i]);
} else { // 奇数索引是数值
values.add(parts[i]);
}
}
System.out.println("日期 (Group 2): " + Arrays.toString(dates.toArray()));
System.out.println("数值 (Group 3): " + Arrays.toString(values.toArray()));
System.out.println("--------------------");
}
}
}代码解析:
运行结果:
--- 逐条匹配结果 --- 区段编号 (Group 1): 250342 日期 (Group 2): [200010, 200011] 数值 (Group 3): [10.00, -2.00] -------------------- 区段编号 (Group 1): 251234 日期 (Group 2): [200011] 数值 (Group 3): [11.00] --------------------
如果需要将所有匹配到的区段编号、日期和数值分别收集到各自的总列表中,可以在 while 循环外部初始化这些列表,并在循环内部添加数据。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class AggregatedDataExtractor {
public static void main(String[] args) {
String regex = "#Section(\d+)\b(?:(?!#Section\d).)*\bJack/M,(\d+\h+[-+]?\d+(?:
" +
"\.\d+)?(?:\s+\d+\h+[-+]?\d+(?:\.\d+)?)*)";
String string = "#Section250342,Main,First/HS/12345/Jack/M,200010 10.00 200011 -2.00,
"
+ "#Section250322,Main,First/HS/12345/Aaron/N,200010 17.00,
"
+ "#Section250399,Main,First/HS/12345/Jimmy/N,200010 12.00,
"
+ "#Section251234,Main,First/HS/12345/Jack/M,200011 11.00";
Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
Matcher matcher = pattern.matcher(string);
List<String> allSectionIds = new ArrayList<>();
List<String> allDates = new ArrayList<>();
List<String> allValues = new ArrayList<>();
while (matcher.find()) {
allSectionIds.add(matcher.group(1)); // 添加区段编号
String[] parts = matcher.group(2).split("\s+");
for (int i = 0; i < parts.length; i++) {
if (i % 2 == 0) {
allDates.add(parts[i]); // 添加日期
} else {
allValues.add(parts[i]); // 添加数值
}
}
}
System.out.println("--- 聚合所有匹配结果 ---");
System.out.println("所有区段编号: " + Arrays.toString(allSectionIds.toArray()));
System.out.println("所有日期: " + Arrays.toString(allDates.toArray()));
System.out.println("所有数值: " + Arrays.toString(allValues.toArray()));
}
}运行结果:
--- 聚合所有匹配结果 --- 所有区段编号: [250342, 251234] 所有日期: [200010, 200011, 200011] 所有数值: [10.00, -2.00, 11.00]
通过上述方法,我们成功地从复杂字符串中精确地提取了所需的三组数据,展示了正则表达式与编程语言协同工作的强大能力。这种模式在处理各种日志解析、数据清洗和信息提取任务中都非常实用。
以上就是使用正则表达式与Java后处理实现复杂字符串多组数据提取的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号