【问题标题】:Regular expression to split on commas not enclosed in parenthesis [duplicate]正则表达式在括号中不括起来的逗号上拆分[重复]
【发布时间】:2009-03-10 00:53:59
【问题描述】:

我无法编写一个正则表达式,在 String.split (Java) 表达式中使用,例如只拆分不在括号中的逗号。

例子:

(54654,4565):(45651,65423),4565:45651,(4565,4564):45651

应该产生 3 个字符串:

  1. (54654,4565):(45651,65423)
  2. 4565:45651
  3. (4565,4564):45651

非常感谢任何帮助。

【问题讨论】:

  • 我知道正则表达式是一行,而且很流畅,但是如果您的需求发生变化,您将如何更改它?如果您发现需要使用大括号而不仅仅是括号,您会寻求帮助吗?我宁愿自己看 10 行显式代码...

标签: java regex


【解决方案1】:

您只需向前看就可以做到这一点,这比向后看更容易使用。

String[] parts = str.split(",(?![^()]*+\\))");

但是其他响应者是对的:如果您自己无法提出这个正则表达式,当需求发生变化时您会怎么做?使用您真正理解的冗长解决方案可能会更好。

【讨论】:

  • 感谢 Alan,它确实有效!我在这里问了这个问题,因为我对正则表达式的经验有限,但渴望学习。当我的需求发生变化时,我将有一个新工具可供我使用,之前没有暴露于后向或前瞻(除了成熟的解析器生成器)。
  • 这很酷。正则表达式就像一个肮脏的编程小秘密。任何提供基于正则表达式的解决方案的人都会习惯于提及它们的局限性和陷阱,因为如果我们不这样做,其他人就会这样做。 ;-)
【解决方案2】:

这行得通:

String regex = "((?<!\\d),)|(,(?!\\d))";

但假定您在逗号的一侧或另一侧有数字以外的其他内容。因此,它并没有真正查看您是否在括号内,而是希望看到它没有在仅由数字包围的逗号上拆分。

因此,如果您正在查看此文本:

"45651:65423,4565:45651"

然后这个解决方案失败(作为一个例子)。如果您更具体地了解您期望的输入类型,我们或许可以根据您的情况量身定制答案。

【讨论】:

  • 我的表达式语言围绕 \\d:\\w 对,看起来像这样(单转义): (\d|((\d(,\d)*)):\ d|((\w(,\w)*))(,(\d|((\d(,\d)*)):\d|((\w(,\w)*)))* ) 示例输入:4565:dewpoint,4568:(temperature,dewpoint),(4565,4568):temperature,(4565,4568):(temperature,dewpoint)
【解决方案3】:

只是提醒一下,如果有任何嵌套,您需要小心。正则表达式在这方面不是很擅长。考虑以下 sn-p:

(a,)b,(c,(d,)e,)

根据您的问题,您只想匹配逗号b。诀窍是表达式通常要么完全贪婪,要么完全不贪婪,几乎没有中间立场。

一个贪婪的表达式会在片段的开头看到(,在最后看到),并在其中获取所有内容,而不管其他地方是否有右括号。 没有会匹配。

一个不贪婪的表达式将只取最小的集合,从头开始。它将匹配逗号b,但也将此段视为一个单元:(c,(d,)。然后它将继续匹配逗号e,因为它已经使用了最后一个(

有一些引擎可以让您处理嵌套级别,但表达式通常很难看且难以维护:最好避免使用该功能,除非您真正理解它。

【讨论】:

  • 谢天谢地,嵌套对我来说并不是真正的要求,在任何给定时间我都只有一层括号。我编写了一个简单的解析器(通过生产规则递归下降),但这个问题让我印象深刻,因为它可以用正确的正则表达式更优雅地解决。
猜你喜欢
  • 2015-06-23
  • 2020-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-01
  • 2018-12-16
相关资源
最近更新 更多