Java 正则表达式:重复捕获组

新手上路,请多包涵

一个项目是一个或多个数字或字符字符串的逗号分隔列表,例如

"12"
"abc"
"12,abc,3"

我正在尝试匹配 Java 中包含零个或多个项目的括号列表,例如

""
"(12)"
"(abc,12)"
"(abc,12),(30,asdf)"
"(qqq,pp),(abc,12),(30,asdf,2),"

对于最后一个示例,它应该分别返回以下匹配组

qqq,pp
abc,12
30,asdf,2

我想出了以下(不正确的)模式

\((.+?)\)(?:,\((.+?)\))*

仅匹配最后一个示例的以下内容

qqq,pp
30,asdf,2

提示?谢谢

原文由 Justin Wong 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 779
2 个回答

这是正确的。在 Java 正则表达式中不能有“可变”数量的捕获组。您的模式有两组:

 \((.+?)\)(?:,\((.+?)\))*
  |___|        |___|
 group 1      group 2

每个组都将包含该组 最后一场比赛 的内容。即, abc,12 将被覆盖 30,asdf,2

相关问题:

解决方案是使用一个表达式(类似于 \((.+?)\) )并使用 matcher.find 迭代匹配项。

原文由 aioobe 发布,翻译遵循 CC BY-SA 3.0 许可协议

使用 ANTLR 文法可以解决这个问题。这确实超出了 RegExp 的合理能力,尽管我相信 Microsoft 在 .Net 中实现的某些较新版本支持此行为。 请参阅其他 SO 问题。 如果您对除 .Net 以外的所有东西都束手无策,那么您最好的选择就是解析器生成器(您不必使用 ANTLR,这只是我个人的喜好)。浏览 ANTLR4 GitHub 页面可以帮助人们开始对更复杂的表达式进行匹配,例如重复匹配组。不需要大量新学习的另一种选择是标记化您想要匹配的字符串输入并提取您想要的部分,但这可能会非常混乱并产生噩梦般的解析块更适合生成的解析器的代码。

原文由 jhyry-gcpud 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题