我尝试接收一个模式和一个字符串,并返回一个组名->匹配结果的Map。
示例:
(?<user>.*)
我想返回一个包含“user”作为键的Map,以及它匹配的任何值。
问题是我似乎无法从Java regex API中获取组名。我只能通过名称或索引获取匹配的值。我没有组名列表,Pattern和Matcher似乎都没有公开这些信息。我已经检查了它的来源,似乎信息是存在的-它只是没有暴露给用户。
我尝试了Java的java.util.regex和jregex。(并且不在乎是否有人建议任何其他库,这些库是好的,受支持的,并且在支持此功能的性能方面很高)。
8条答案
按热度按时间f0ofjuux1#
Java中没有API来获取命名捕获组的名称。我认为这是一个缺失的功能。
简单的方法是从模式中挑选出候选的命名捕获组,然后尝试从匹配中访问命名组。换句话说,在插入匹配整个模式的字符串之前,您不知道命名捕获组的确切名称。
用于捕获命名捕获组名称的
Pattern
是\(\?<([a-zA-Z][a-zA-Z0-9]*)>
(基于Pattern
类文档派生)。(The困难的方法是实现正则表达式的解析器并获取捕获组的名称)。
示例实现:
不过,这种实现方式有一个警告。它目前不能在
Pattern.COMMENTS
模式下使用regex。1bqhqjot2#
这是解决这个问题的第二个简单方法:我们将调用Pattern类中的非公共方法
namedGroups()
来获得一个Map<String, Integer>
,它通过Java Reflection API将组名Map到组号。这种方法的优点是,我们不需要一个包含正则表达式匹配的字符串来找到确切的命名组。就我个人而言,我认为这不是一个很大的优势,因为在输入字符串中不存在与正则表达式匹配的正则表达式时,知道正则表达式的命名组是无用的。
但是,请注意the drawbacks:
namedGroups()
方法中没有太多发生)。我不知道 * 性能冲击如何影响整体性能 *,所以请在您的系统上进行测量。quhf5bfb3#
你想使用小型name-regexp库。它是一个围绕
java.util.regex
的瘦 Package 器,支持Java 5或6用户的命名捕获组。示例用法:
Maven:
参考文献:
f0ofjuux4#
我在“真实的”模式中使用了正则表达式组的模式来获取组的名称,如下所示:
然后,我将名称和值添加到HashMap<String,String>中:
i2byvkas5#
没有办法用标准的API做到这一点。您可以使用反射来访问以下内容:
如果你不关心索引,使用Map的键集。
dwbf0jvd6#
Java版本20之前的版本无法通过标准API实现这一点。
这是一个长期公认的需求,JDK Bug System issue JDK-7032377 "MatchResult and Pattern should provide a way to query names of named-capturing groups"就是证明。此问题要求通过
MatchResult
和Pattern
API公开命名捕获组。这个问题是在2011年创建的,该功能最终在2022年为Java 20实现。dbf7pr2w7#
public Map<String, Integer> namedGroups()
可能很快会在Java 20中出现吗?(我跟踪了前面提到的JDK bug ticket JDK-7032377中的链接。它已经获得了一些牵引力,this commit。
mtb9vblg8#
从Java 20开始,这可以在
MatchResult
上使用namedGroups
方法(Matcher
实现)来实现: