Java中是否有简洁方法可从正则表达式中仅提取字符串字面量?
解决方案
你需要做的本质是解析正则表达式的抽象语法树(AST),提取所有字面量节点的取值,自己用正则去拆正则结构很容易遇到各种边界问题(比如嵌套字符类、多重转义、Unicode属性转义等),用成熟的正则解析库是最稳妥的方案。
推荐方案:使用Google RE2J 库
RE2J是谷歌开源的正则表达式实现,它的解析器API是公开的,可以直接拿到正则的AST结构,无需依赖JDK内部API,兼容性好,Groovy可以直接调用。
依赖引入
Maven配置:
<dependency> <groupId>com.google.re2j</groupId> <artifactId>re2j</artifactId> <version>1.7</version> </dependency>
Gradle配置:
implementation 'com.google.re2j:re2j:1.7'
示例代码(Groovy)
import com.google.re2j.Parser import com.google.re2j.RegexNode def extractRegexLiterals(String regex) { def rootNode = Parser.parse(regex) def literalCollector = [] traverseAst(rootNode, literalCollector) return literalCollector.join('') } def traverseAst(RegexNode node, List collector) { switch (node.type) { // 普通字符串字面量直接收集 case RegexNode.Type.LITERAL: collector.add(node.getString()) break // 转义结构处理,比如\\、\123这类转义值 case RegexNode.Type.ESCAPE: collector.add((char) node.escapeValue as String) break // 其他类型节点(通配符、量词、字符类、分组等)递归遍历子节点 default: node.children.each { traverseAst(it, collector) } } } // 测试用例 assert extractRegexLiterals(/\d{4}abc.*/) == 'abc' assert extractRegexLiterals(/\\123/) == '\\123'
其他可选方案
- 如果你不想引入第三方依赖,可以通过反射调用JDK
java.util.regex.Pattern内部的AST解析逻辑,但该实现是JDK私有API,不同JDK版本可能存在兼容性问题,不建议生产环境使用。 - 如果需要自定义处理逻辑,也可以用ANTLR现成的正则语法生成解析器,不过成本比直接用RE2J高很多。
注意事项
如果你的业务逻辑需要过滤字符类(比如[abc])里的字面量,只需要在遍历AST的时候,判断节点类型为CHAR_CLASS时跳过子节点遍历即可,可以根据自己的需求灵活调整遍历逻辑。
内容的提问来源于stack exchange,提问作者Kramer
相关产品推荐
相关产品推荐

