如何在 Java 中获取 Group.Captures(来自 C# 中的 RegEx)的行为?
Posted
技术标签:
【中文标题】如何在 Java 中获取 Group.Captures(来自 C# 中的 RegEx)的行为?【英文标题】:How to get behavior of Group.Captures (from RegEx in C#) in Java? 【发布时间】:2012-02-22 02:05:03 【问题描述】:我正在寻找的是在 Java 的正则表达式 API 中以最易于使用的方式模仿 C# 正则表达式(我非常喜欢)的行为。
基本上,C# 允许您通过访问Group
内Group
对象实例的Captures
属性来捕获正则表达式中“嵌套”组的闭包@ es。功能描述在这里:MSDN。
例如看下面的代码:
public static void main(String[] args)
Pattern pattern = Pattern.compile("(abc((([\\d]+)\\s?)+)def\\s?)+?");
Matcher matcher = pattern.matcher("abc123def abc567 341 123 789def");
while(matcher.find())
System.out.println(matcher.group(3));
Java 中的输出是:
123
789
因此,如您所见,Java 看不到除(最后一个)789 之外的其他捕获。在 C# 中,您将能够在 Captures
属性中看到 567、341、123 和 789。
不幸的是,我看到在 Java 中我只能访问嵌套组 ([\\d]+)
的一个捕获,我无法找到一种方法来捕获嵌套组的其他捕获。问题基本上是“我在这里遗漏了什么吗?”。
我知道我可以在更大组的匹配字符串上使用另一个正则表达式匹配器。我希望将所有这些都放在一个充满 cmets 的大型 RegEx 中,并且易于在(非常酷的)工具“Regulator v2”中进行测试。我也知道上面的例子可以在没有嵌套组的情况下完成,但这只是一个基于具有>20组的真实日志解析器RegEx的粗略示例,只是为了解释问题所在。
编辑:我介绍了整个 Java 示例以避免对问题的误解。
【问题讨论】:
这就是通常的正则表达式的工作方式,每个捕获组只保存一个值,.NET 是一个例外。\d+
可以很好地用于您的示例。请随时提供更完整的案例/示例,以便我们为您提供帮助。
我试图在上面的例子中尽可能准确,由于正则表达式的复杂性,现实生活中的例子会使这个问题变得不可读。另一方面,我确实承认您所说的话,并将尝试忘记 .Net 方式并将正则表达式重构为更合适和更直接的方法
【参考方案1】:
这在java中是不可能实现的。
Java Matcher
类将返回每个匹配项中子组的最后一个匹配项。
那就是:
对于正则表达式:(\w(\d))+
字符串 a1b2c3
返回的组将为 ["a1b2c3", "c3", "3"]。
如果正则表达式更改为(\w(\d))
,那么它将返回匹配项:
["a1", "a1", "1"]
、["b2", "b2", "2"]
、["c3", "c3", "3"]
【讨论】:
您的头像缺少一个巨魔脸。 (-; 谢谢,我也认为此时如果没有额外的正则表达式在第一级正则表达式的匹配组中使用 Java 是不可能的【参考方案2】:如果您使用Matcher
对象,您可以遍历所有匹配项并获取每个匹配项的组。
基本上你这样做:
while( matcher.find() )
matcher.group(3); //group 0 is the entire match, group 1 and 2 are the outer groups
但是请注意,您的正则表达式需要进行一些调整,因为它会匹配 abc567 341 123def
例如。 AFAIK,如果您想要的话,您无法从一场比赛中获得 567 341 和 123 组。
您可以使用此表达式获取abc
和def
之间的数字组,然后在第二步中拆分这些组:(?<=abc)((?:\d+\s?)+)(?=def)
此表达式将返回123
和567 341 123
,并且在空格处拆分它们将产生一个带有每个单独数字的字符串数组,即"123".split("\\s+")
->"123"
和"567 341 123".split("\\s+")
-> "567", "341", "123"
【讨论】:
同意这是一种方法。如果可以的话,我想避免这种方法,因为在 C# 中我不必走那么长的路。以上是关于如何在 Java 中获取 Group.Captures(来自 C# 中的 RegEx)的行为?的主要内容,如果未能解决你的问题,请参考以下文章