本文详解如何通过 java 正则表达式精准提取文件名中特定位置的中间段(如从 aa_bb_cc_20-300.tsv 提取 cc_20-300),涵盖模式设计原理、完整可运行代码、边界注意事项及替代方案建议。
本文详解如何通过 java 正则表达式精准提取文件名中特定位置的中间段(如从 aa_bb_cc_20-300.tsv 提取 cc_20-300),涵盖模式设计原理、完整可运行代码、边界注意事项及替代方案建议。
在 Java 文件处理场景中,常需从带分隔符(如下划线 _)和扩展名(如 .tsv)的文件名中提取结构化子串。例如,给定文件名 AA_BB_CC_20-300.tsv,目标是跳过前两段下划线分隔的部分(AA 和 BB),保留后续连续两段(CC_20-300),并剔除扩展名。此时,正则表达式是简洁且可控的解决方案。
核心正则模式为:
^[^_]+_[^_]+_([^_]+_[^_]+)\..*$
该模式含义分解如下:
- ^:字符串起始锚点;
- [^_]+:匹配一个或多个非下划线字符(即第一段,如 AA);
- _:字面量下划线;
- [^_]+:第二段(如 BB);
- _:第二个下划线;
- ([^_]+_[^_]+):捕获组 1 —— 精确匹配“第三段 + 下划线 + 第四段”,即 CC_20-300;其中 [^_]+ 确保每段内部不含下划线,避免跨段误匹配;
- \.:转义的点号(.),匹配字面量 .(扩展名分隔符);
- .*:匹配其后任意字符(扩展名,如 tsv);
- $:字符串结束锚点。
✅ 完整可运行示例代码:
立即学习“Java免费学习笔记(深入)”;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class FilenameExtractor {
public static void main(String[] args) {
String filename = "AA_BB_CC_20-300.tsv";
// 正则:跳过前两段下划线分隔内容,捕获第三+第四段,并忽略扩展名
String patternString = "^[^_]+_[^_]+_([^_]+_[^_]+)\..*$";
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher(filename);
if (matcher.find()) {
String extracted = matcher.group(1); // 获取捕获组内容
System.out.println("Extracted: " + extracted); // 输出:CC_20-300
} else {
System.err.println("Filename format mismatch: expected at least 4 underscore-separated parts before extension");
}
}
}⚠️ 重要注意事项:
- 该正则强依赖固定结构:要求文件名严格满足「至少 4 段下划线分隔内容 + 扩展名」(如 X_Y_Z_A.ext)。若实际数据存在变长(如 A_B_C_D_E.tsv),需调整捕获逻辑(例如改用 _(?:[^_]+_){n}([^_]+_[^_]+) 动态控制偏移);
- 不推荐用于含多点扩展名(如 file.tar.gz)或无扩展名场景——应先用 FilenameUtils.getBaseName()(Apache Commons IO)或 Path.getFileName() 预处理;
- 性能敏感场景下,若格式高度稳定,可考虑 String.split("_") 配合数组索引(更直观、开销更低),但正则在复杂模式(如混合数字/字母/符号边界)中更具扩展性。
? 总结:正则表达式是处理结构化文件名切片的有力工具。本例中的模式兼顾准确性与可读性,通过锚点、否定字符类和精确捕获组,安全地剥离前缀与后缀,直达目标子串。实践中建议结合单元测试覆盖异常输入(空字符串、少于 4 段、缺失扩展名等),确保鲁棒性。


















