
在数据处理中,我们经常需要从非结构化的文本中提取特定信息。考虑以下字符串数据,其中包含多个以#section开头的记录:
#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
我们的目标是从所有包含特定标识符(例如/Jack/M)的行中,提取以下三组数据:
值得注意的是,日期和数值总是成对出现,且每行可能包含一个或多个日期-数值对。这种动态数量的子项使得仅使用单一正则表达式直接捕获所有三组数据变得复杂。
为了有效解决这个问题,我们将采用一种混合方法:
这种方法结合了正则表达式的模式匹配能力和编程语言的数据处理灵活性,是处理此类复杂数据提取任务的有效策略。
立即学习“Java免费学习笔记(深入)”;
我们将使用的正则表达式如下:
#Section(d+)(?:(?!#Sectiond).)*Jack/M,(d+h+[-+]?d+(?:.d+)?(?:s+d+h+[-+]?d+(?:.d+)?)*)
现在,我们来逐一解析这个正则表达式的各个部分:
通过这个正则表达式,我们成功地将问题分解为两个主要的捕获组:区段编号(组1)和所有日期-数值对组成的字符串(组2)。
接下来,我们将使用Java语言来应用这个正则表达式,并对捕获到的数据进行后处理。
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<>();
// 捕获组1:区段编号
String sectionNumber = matcher.group(1);
System.out.println("区段编号 (Group 1): " + sectionNumber);
// 捕获组2:日期和数值的组合字符串
String dateTimeValuesString = matcher.group(2);
// 后处理:分离日期和数值
String[] parts = dateTimeValuesString.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();
}
}
}在上述代码中,当matcher.find()找到一个匹配项后:
运行上述代码,将得到以下输出,展示了对每条匹配记录的单独处理结果:
--- 逐条匹配结果 --- 区段编号 (Group 1): 250342 日期 (Group 2): [200010, 200011] 数值 (Group 3): [10.00, -2.00] 区段编号 (Group 1): 251234 日期 (Group 2): [200011] 数值 (Group 3): [11.00]
如果需要将所有匹配到的区段编号、日期和数值分别收集到各自的全局列表中,可以在循环外部初始化列表,并在循环内部添加数据。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DataAggregator {
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> allSectionNumbers = new ArrayList<>();
List<String> allDates = new ArrayList<>();
List<String> allValues = new ArrayList<>();
while (matcher.find()) {
// 捕获组1:区段编号
allSectionNumbers.add(matcher.group(1));
// 捕获组2:日期和数值的组合字符串
String dateTimeValuesString = matcher.group(2);
// 后处理:分离日期和数值并添加到全局列表
String[] parts = dateTimeValuesString.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("所有区段编号 (Group 1): " + Arrays.toString(allSectionNumbers.toArray()));
System.out.println("所有日期 (Group 2): " + Arrays.toString(allDates.toArray()));
System.out.println("所有数值 (Group 3): " + Arrays.toString(allValues.toArray()));
}
}运行上述聚合代码,将得到以下输出:
--- 聚合所有匹配结果 --- 所有区段编号 (Group 1): [250342, 251234] 所有日期 (Group 2): [200010, 200011, 200011] 所有数值 (Group 3): [10.00, -2.00, 11.00]
本教程展示了如何通过结合正则表达式的强大模式匹配能力和编程语言的灵活数据处理逻辑,来解决从复杂字符串中提取动态分组数据的挑战。
关键点回顾:
这种方法不仅适用于Java,也适用于任何支持正则表达式和基本字符串操作的编程语言。在实际应用中,应根据具体的数据格式和需求,灵活调整正则表达式和后处理逻辑,以实现最精确高效的数据提取。
以上就是使用正则表达式与后处理技术从复杂字符串中提取动态分组数据:以Java为例的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号