正则表达式:按括号分割,忽略引号内的嵌套括号。

4
我的程序将SQL VALUES多行字符串解析为单行字符串数组。
典型的输入字符串如下:
(11,'-1','Service A (nested parentheses)','en') (22,'-2','Service B (nested parentheses)','en')

期望输出:

  • 分组 1:11,'-1','服务A(嵌套括号)','en'
  • 分组 2:22,'-2','服务B(嵌套括号)','en'

我尝试了以下正则表达式,但只有部分成功:

\(('.*?'|.*?)\)

在正则表达式中,应该如何正确地处理这个问题呢?

编辑:

  • 目标平台是Java 6/7
  • 不需要将括号替换为换行符 - 只需要捕获组

1
什么语言?PCRE支持递归正则表达式,可以实现这一点。请参阅http://www.regular-expressions.info/refrecurse.html。 - Barmar
如果你正在使用Lua,那么你可以使用以下代码来打印出一个表格的所有键和值:(原文链接:http://codepad.org/8IzarHjG) - hjpotter92
1
@Barmar:由于引号内的括号被忽略,因此您不需要递归。使用\((?>'[^']*'|[^')]++)*\)可以匹配一个项目。 - Casimir et Hippolyte
3个回答

2

编辑:根据您的评论关于表情符号,我建议采用另一种方法:

(?<=\()(?:'[^']*'|[,\s]+|\d+)+(?=\))

请查看演示。假设您的令牌是由单引号或数字包围的字符串,这是正确的吗?

原始答案

对于一个潜在的嵌套级别,在大多数正则表达式中,包括Java,这将起作用:

(?<=\()(?:[^()]+|\([^)]+\))+

请查看演示

它是如何工作的?

  1. 回顾先前的字符是一个开放括号(
  2. 非捕获组与+量词匹配一个或多个: (i)任意数量的不是开放或关闭括号的字符, 或者 | (ii)完整的(括号表达式)

如果你想确保容器是平衡的,在结尾处添加一个前瞻:

(?<=\()(?:[^()]+|\([^)]+\))+(?=\))

这是一个令人印象深刻的正则表达式!它似乎不支持笑脸符号:('Android KitKat(4.4)设备',':)','&:*(','Slendrina:The Cellar(免费版)') - Dan M
@danm 请查看我回答的顶部新正则表达式,如果它符合您的需求或者有什么遗漏,请告诉我 :) - zx81
@danm 修复后,您的问题是否已解决?我之所以问是因为我注意到您尚未在StackOverflow上投票。如果这个答案或其他答案解决了您的问题,请考虑通过单击左侧的复选标记“接受它”来接受它,因为这就是声望系统的工作方式(接受答案会将声望授予回答者和您)。当然,没有义务这样做。稍后当您有更多声望时,也可以对问题进行投票。感谢您收听我20秒的SO声望教程。 :) - zx81
太棒了,我差点放弃了,直到我找到了这个正则表达式。 - Eddy Ekofo

1
pattern.compile("\\(((?:'[^']*'|[^'\\(\\)]+)+)\\)");

RegexPlanet 点击 Java 链接。

正则表达式的主要部分是 '[^']*'|[^'\(\)] - 由单引号包围的任意一系列字符或不包含单引号和圆括号的任意字符串。这避免了使用回溯,虽然Casimir et Hippolyte建议使用回溯可能更有效(我对Java中回溯的性能方面不是特别熟悉)。


0

有一些注意事项:

/\(.*\)/\1/

将删除周围的括号,并

/\) \(/\r/g

将按照您的示例输入换行符

注意事项:

  • 此正则表达式为广义形式,因为您没有指定哪种正则表达式实现
  • 仅在输入与您的示例非常相似时有效

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接