如何修改正则匹配含空格键值对且不违反Sonar S5998规则
问题根因
你触发Sonar S5998规则的核心原因是原正则使用了嵌套量词:(?: *\p{Alnum}+)+,外层+和内层+叠加会导致正则引擎在匹配失败时产生指数级回溯,大输入场景下确实存在栈溢出风险。
解决方案
直接把值的匹配逻辑改成匹配「非逗号的所有字符」即可,完全避免嵌套量词,同时天然支持带空格的值:
- 替换
keyValuePattern的正则表达式,删除嵌套量词结构 - 拆分键值对时增加拆分上限,避免值本身包含等号时拆分错误,同时对值做首尾空格修剪
修改后的正则&核心代码
// 正则无嵌套量词,匹配规则:字母数字键 + 等号(前后允许空格) + 任意非逗号字符(到下一个键值对分隔符为止) private static final Pattern keyValuePattern = Pattern.compile("\\p{Alnum}+ *= *[^,]+");
键值对拆分逻辑调整:
// 加limit=2避免值中包含等号时拆分错误,trim去除首尾多余空格 final String[] elements = matcher.group().split("=", 2); mappedValues.put(elements[0].trim(), elements[1].trim());
完整可运行修改后代码
import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; public class PatternMatchTest { private static final Pattern keyValuePattern = Pattern.compile("\\p{Alnum}+ *= *[^,]+"); private static final Pattern quotesPattern = Pattern.compile("\"(.*?)\"", Pattern.DOTALL); public static void main(final String[] args){ final String line = "\"$0 = test 1, $1 = test2, $2 = test3\""; final Map<String, String> mappedValues = new HashMap<>(); final Matcher quotesMatcher = quotesPattern.matcher(line); if (quotesMatcher.find()) { final String valueInQuotes = quotesMatcher.group(0).replace("$", " ").replace(" = ", "="); final Matcher matcher = keyValuePattern.matcher(valueInQuotes); while (matcher.find()) { final String[] elements = matcher.group().split("=", 2); mappedValues.put(elements[0].trim(), elements[1].trim()); } } mappedValues.entrySet().forEach(entry -> { System.out.println(entry.getKey() + "->" + entry.getValue()); }); } }
输出结果
和原预期完全一致:
0->test 1 1->test2 2->test3
方案优势
- 无嵌套量词,完全符合Sonar S5998规则要求,不存在回溯溢出风险
- 天然支持值中包含任意空格,甚至支持值本身包含等号的场景
- 匹配效率远高于原有分组重复写法,大输入下性能更优
内容的提问来源于stack exchange,提问作者thepen
相关产品推荐
相关产品推荐

