正则实现按L后编号分组匹配拆分ArrayList格式化字符串
正则匹配L/C后数字并按L编号分组实现方案
原有正则问题说明
- 硬编码C后仅支持1位数字、L编号最大为100的限制,不符合L、C后数字最多支持4位的需求
- 反向引用逻辑存在缺陷,跨条目匹配时容易将不同L分组的内容错误拼接
- 未兼容条目间的空格、多种结尾后缀(
_OK/_KO/无后缀)、独立etc...片段的场景
稳定实现方案
优先使用「单条目正则匹配+代码层面聚合分组」的实现逻辑,容错率远高于纯正则一次性匹配全部分组,适配所有格式变体。
核心匹配正则
用于提取每个独立的L开头条目,同时捕获L、C后的数字:
L(\d{1,4})_C(\d{1,4})_.*?(?=\s*,?\s*L\d{1,4}_|$)
正则规则说明:
L(\d{1,4}):匹配L前缀,捕获1-4位的L后数字作为分组依据_C(\d{1,4}):匹配C前缀,捕获1-4位的C后数字,符合L、C数字规则一致的要求_.*?(?=\s*,?\s*L\d{1,4}_|$):非贪婪匹配条目剩余内容,通过正向预查判断下一个条目起始或字符串结尾,不会跨条目吞入内容
Java代码实现
针对你使用的ArrayList存储场景,直接通过有序Map按L编号聚合即可:
import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; public class LcGroup { public static void main(String[] args) { // 替换为你的实际al1集合即可 List<String> al1 = Arrays.asList( "L1_C1_0", "L1_C2_\"11229\"", "L1_C2_\"CHK_CASHING\"_OK", "etc...", "L1_C100_\"FR45248624892\"", "L2_C1_0", "L2_C2_\"11229\"", "L2_C2_\"CHK_CASHING\"_OK", "etc...", "L2_C100_\"FR45248624892\"_KO", "L3_C1_0", "L3_C2_\"11229\"", "L3_C2_\"CHK_CASHING\"_OK", "etc...", "L3_C100_\"FR45248624892\"_KO", "L4_C1_0", "L3_C2_\"11229\"", "L4_C2_\"CHK_CASHING\"_OK", "etc...", "L4_C100_\"FR45248624892\"_OK" ); // 拼接集合所有内容为完整字符串 String fullContent = String.join(", ", al1); Pattern itemPattern = Pattern.compile("L(\\d{1,4})_C(\\d{1,4})_.*?(?=\\s*,?\\s*L\\d{1,4}_|$)"); Matcher matcher = itemPattern.matcher(fullContent); // TreeMap自动按L编号数值升序存储,避免字符串排序导致L10排在L2前的问题 Map<Integer, List<String>> groupMap = new TreeMap<>(); while (matcher.find()) { String item = matcher.group().trim(); int lNum = Integer.parseInt(matcher.group(1)); int cNum = Integer.parseInt(matcher.group(2)); // 过滤C后数字超出1-9999范围的非法条目,不需要可删除该判断 if (cNum < 1 || cNum > 9999) continue; groupMap.computeIfAbsent(lNum, k -> new ArrayList<>()).add(item); } // 逐行打印分组结果 for (List<String> group : groupMap.values()) { System.out.println(String.join(", ", group)); } } }
输出效果
运行后输出和预期完全一致:
L1_C1_0, L1_C2_"11229", L1_C2_"CHK_CASHING"_OK, etc..., L1_C100_"FR45248624892" L2_C1_0, L2_C2_"11229", L2_C2_"CHK_CASHING"_OK, etc..., L2_C100_"FR45248624892"_KO L3_C1_0, L3_C2_"11229", L3_C2_"CHK_CASHING"_OK, etc..., L3_C100_"FR45248624892"_KO, L3_C2_"11229" L4_C1_0, L4_C2_"CHK_CASHING"_OK, etc..., L4_C100_"FR45248624892"_OK
调整说明
- 如果
etc...这类独立片段需要归属于下一个L分组,只需调整正则预查逻辑的匹配顺序即可 - 如果需要保留原始字符串中的空格、标点格式,删除
trim()、调整String.join的连接符即可
内容的提问来源于stack exchange,提问作者Mouss Gosling
相关产品推荐
相关产品推荐

