0

正则表达式如何给我输出

se,dc(fr(lo)),km(ji)(hn),...从一个字符串az(se)(dc(fr(lo)))(km(ji)(hn))...

谁能告诉我如何编写正则表达式来获取括号之间的文本,以便我可以在不使用任何外部包/库的情况下实现上述结果,因为它仅用于学习目的。

4

2 回答 2

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 内,因此会产生递归效果。

演示

演示

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

输出

瑟
直流(fr(lo))
公里(ji)(hn)
()aaa(()())(ff(dd)aa)
于 2013-05-10T08:55:47.973 回答
1

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

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

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

用作:

my @list = $str =~ /\(((?:[^()]++|(?R))*+)\)/g;
于 2013-05-10T10:06:37.030 回答