单行模式下正则匹配Java注解时含逗号场景重复捕获组失效问题
解决方案
首先明确核心限制:绝大多数正则引擎的重复捕获组仅会保留最后一次匹配的结果,无法直接存储多次重复的子组内容,因此根据使用场景提供两种可行方案:
方案1:两步匹配(全语言兼容,推荐)
该方案兼容性最高,适配Java、JavaScript、Python等所有主流语言的正则实现。
步骤1:提取注解括号内的全部内容
使用如下正则,开启单行(dotall)模式,捕获组1即为注解括号内所有键值对的原始内容:
^\s*@MyCustomQuery\(\s*(.*?)\s*\)
步骤2:全局匹配每个键值对
使用如下正则,对步骤1提取的内容开启全局匹配模式,遍历所有匹配结果即可得到全部键值对:
\s*([^\s=,]+)\s*=\s*(?:"([^"\\]*(?:\\.[^"\\]*)*)"|([^\s,]+))
匹配结果说明:
- 分组1:键名(如
name、query、resultClass) - 分组2:双引号包裹的值内容(如字符串、SQL语句,自动忽略内部的逗号、换行、转义双引号)
- 分组3:无引号的标识符值(如类字面量
Professor.class、数字常量等)
方案2:单正则一次性捕获(仅支持PCRE2、.NET等高级引擎)
如果使用支持重复捕获组堆栈的引擎(如PCRE2开启J标志、.NET正则),可使用如下单正则一次性捕获所有键值对:
^\s*@MyCustomQuery\((?:\s*(?<key>[^\s=,]+)\s*=\s*(?<value>"[^"\\]*(?:\\.[^"\\]*)*"|[^\s,]+)\s*(?:,|(?=\))))+\s*\)
匹配完成后遍历key、value命名捕获组的历史结果,即可得到全部键值对。
原有正则失效原因说明
你之前编写的正则存在两个核心问题:
- 未区分值内部的逗号与键值对分隔逗号:贪婪模式的
.+会吞掉所有内容直到字符串末尾,无法正确识别值的边界 - 没有处理右括号终止逻辑:正则仅匹配到逗号就结束,没有适配最后一个键值对后直接接右括号的场景
内容的提问来源于stack exchange,提问作者BBacon
相关产品推荐
相关产品推荐

