正则表达式:匹配嵌套括号中的文本。

时间:2013-05-10 07:49:58

标签: regex perl

正则表达式如何为我提供输出

来自字符串se,dc(fr(lo)),km(ji)(hn),...

az(se)(dc(fr(lo)))(km(ji)(hn))...

有人能告诉我如何编写正则表达式来获取parantheses之间的文本,以便我可以实现上面的结果,而不使用任何外部包/库,因为它仅用于学习目的。

2 个答案:

答案 0 :(得分:2)

这是递归正则表达式

的典型示例
\(((?:[^()]++|\((?1)\))*+)\)

说明

让我们打破正则表达式:

\(              # Literal (
(               # Start of capturing group 1
  (?:           # Start of non-capturing group
     [^()]++    # Match characters other than ()
     |          # OR
     \((?1)\)   # Recursively match bracketed () content
  )*+           # End of non-capturing group, and repeat the whole group zero or more times.
)               # End of capturing group 1
\)              # Literal )

开头和结尾的2个文字括号()是为了确保我们匹配括号内的文字。如果没有它们,它将使用平衡括号匹配部分文本。

(?:[^()]++|\((?1)\))*+部分描述了一对括号内的模式:

  • 可以有非括号()字符序列
  • 或括号(...)部分,以(开头,后跟(?:[^()]++|\((?1)\))*+(由于(?1) 子程序调用的影响)和以)结尾。

并且可能有0个或多个非括号序列的实例,并且括号内的(...)部分相互交错。

(?1)称为子程序调用,它允许您与捕获组分隔的子模式匹配。在这种情况下,由于(?1)位于捕获组1内部,因此会产生递归效果。

演示

DEMO

my $str = "az(se)(dc(fr(lo)))(km(ji)(hn))(()aaa(()())(ff(dd)aa))";
my @arr = $str =~ /\(((?:[^()]++|\((?1)\))*+)\)/g;
print join("\n", @arr)

输出

se
dc(fr(lo))
km(ji)(hn)
()aaa(()())(ff(dd)aa)

答案 1 :(得分:1)

nhahtdh正则表达式的略短版本:

\(((?:[^()]++|(?R))*+)\)

您可以通过递归到整个表达式((?R))而不是子表达式((?1))来避免重复文字括号。否则它是一样的。

用作:

my @list = $str =~ /\(((?:[^()]++|(?R))*+)\)/g;