在两个花括号之间匹配所有的括号

5
我正试图找到一个正则表达式模式,可以匹配在 {} 之间的所有括号(及其内容)。
示例: - {foo (i,j) bar} 应匹配 (i,j) - {(i,j) foo (k,l) bar (m,n,o)} 应匹配 (i,j)(k,l)(m,n,o) - foo (i,j) bar 不应匹配任何内容,因为字符串不在花括号之间 - {foo (i,j) bar} (k,l) 应匹配 (i,j),但不应匹配 (k,l),因为后者不在花括号内
我尝试使用以下模式:(?<=\{)[^\(].*\(.*?\).*(?=\})。这个模式匹配了第一、二和四个示例,但匹配了花括号内所有内容,而不仅是括号和它们的内容。

你是用PHP、C#、JavaScript、Java、Ruby等编程语言来编写这个解决方案的吗? - Wiktor Stribiżew
最终,我将在R中使用它。 - Christian
1个回答

5

您可以使用

(?:\G(?!\A)|{)[^{}]*?\K\([^()]*\)

查看正则表达式演示。如果您确保右侧有一个闭合的},请在末尾添加(?=[^{}]*})正向预查:

(?:\G(?!\A)|{)[^{}]*?\K\([^()]*\)(?=[^{}]*})

请查看此正则表达式演示

细节

  • (?:\G(?!\A)|{) - 匹配前一个成功的匹配的结尾或 { 字符
  • [^{}]*? - 零个或多个非 {} 字符,尽可能少地匹配
  • \K - 匹配重置运算符,从当前完整匹配内存缓冲区中删除到目前为止匹配的所有文本
  • \( - 一个 ( 字符
  • [^()]* - 零个或多个非 () 字符,尽可能多地匹配
  • \) - 一个 ) 字符
  • (?=[^{}]*}) - 紧接在右侧,必须有零个或多个非 {} 字符,然后是一个 }

请查看在线R演示

x <- "{(i,j) foo (k,l) bar (m,n,o)} should match on (h,j), (a,s), and (i,o,g)."
regmatches(x, gregexpr("(?:\\G(?!\\A)|{)[^{}]*?\\K\\([^()]*\\)(?=[^{}]*})", x, perl=TRUE))
# [[1]]
# [1] "(i,j)"   "(k,l)"   "(m,n,o)"

你不知道我尝试解决这个问题多久了。谢谢你,Wiktor,它完美地解决了! - Christian
1
@Christian 刚刚添加了带有基本 R 解决方案的 R 代码。请注意,您将无法使用当前模式使用 stringr 实现此目标,您需要删除 \K,捕获括号匹配模式并使用 stringr::str_match_all。如果您需要匹配嵌套括号,则只能使用基本 R 解决方案进行一些修改才能实现,如果需要,请告诉我。 - Wiktor Stribiżew
1
谢谢,它完美地工作了。对于其他人的两个评论,如果有用的话:1)使用Wiktor提出的regmatches并将invert参数设置为TRUE将删除匹配项。2)另一个添加到Wiktor的模式可能很有用。在我的情况下,当括号在花括号内部时,我还想忽略带有特定单词(之前没有空格)的括号,例如“first”,“last”等。然后,负回顾(?<!first|last)可能很有用,例如: (?:\G(?!\A)|{)[^{}]*?\K(?<!first|last)\([^()]*\)(?=[^{}]*}) - Christian

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