正则校验文本行:解决字段内数字多空格误判问题
问题背景与校验规则
- 待校验文本行格式示例:
"Field1" "Field2" "Field3 Field_3.1 Field3.2" 23 3445 "Field5",字段间以单个空格作为分隔符 - 核心校验规则:
- 字段外部出现2个及以上连续空格时,该行判定为无效
- 双引号包裹的文本字段内部允许任意空格(包括包含数字子字段的场景,如
"Field3 Field_3.1 123")
现有正则的问题
原正则表达式"[\"^\\n]\\s{2,}?(\".*\")|\\s\\s\\d|\\d\\s\\s"存在两个关键问题:
- 误判合法场景:会将双引号内包含多空格+数字的合法字段判定为无效
- 存在正则回溯问题,匹配效率低下
正确的正则匹配方案
核心思路是先完整匹配所有合法字段(跳过双引号内的内容),再检查字段外部的连续多空格,既避免误判引号内的合法空格,又消除回溯问题。
推荐使用以下正则表达式:
String spacePattern = "\\G(?:\"[^\"]*\"|\\S+)(?:\\s(?:\"[^\"]*\"|\\S+))*\\K\\s{2,}|^\\s{2,}|\\s{2,}$";
正则逻辑说明:
\\G:锚定上一次匹配的结束位置,确保从左到右逐段匹配合法字段(?:\"[^\"]*\"|\\S+):匹配单个合法字段,要么是双引号包裹的内容(\"[^\"]*\",无回溯的非贪婪匹配),要么是非空格的普通字段(\\S+)(?:\\s(?:\"[^\"]*\"|\\S+))*:匹配后续的「单个空格+合法字段」组合,确保字段间仅为单个空格\\K:重置匹配起始位置,忽略前面的合法内容,只捕获后续的非法多空格^\\s{2,}|\\s{2,}$:额外匹配行首或行尾的连续多空格
修改后的测试代码
public class SpaceValidation { public static void main(String[] args) { String spacePattern = "\\G(?:\"[^\"]*\"|\\S+)(?:\\s(?:\"[^\"]*\"|\\S+))*\\K\\s{2,}|^\\s{2,}|\\s{2,}$"; // 合法:引号内包含多空格+数字 String line1 = "\"Field3 Field_3.1 123\" \"abc\" 456"; // 合法:普通字段用单个空格分隔 String line2 = "Field3 Field_3.1 123"; // 无效:字段间存在两个连续空格 String line3 = "\"Field1\" \"Field2\" 23"; // 无效:行首存在连续多空格 String line4 = " \"Field1\" \"Field2\""; // 无效:行尾存在连续多空格 String line5 = "\"Field1\" \"Field2\" "; Pattern pattern = Pattern.compile(spacePattern); checkLineValidity(pattern, line1); checkLineValidity(pattern, line2); checkLineValidity(pattern, line3); checkLineValidity(pattern, line4); checkLineValidity(pattern, line5); } private static void checkLineValidity(Pattern pattern, String line) { Matcher matcher = pattern.matcher(line); if (matcher.find()) { System.out.println("无效行:" + line); } else { System.out.println("合法行:" + line); } } }
内容的提问来源于stack exchange,提问作者Rajesh2389
相关产品推荐
相关产品推荐

