正则表达式如何给我输出
se,dc(fr(lo)),km(ji)(hn),...
从一个字符串az(se)(dc(fr(lo)))(km(ji)(hn))...
谁能告诉我如何编写正则表达式来获取括号之间的文本,以便我可以在不使用任何外部包/库的情况下实现上述结果,因为它仅用于学习目的。
这是递归正则表达式的经典示例:
\(((?:[^()]++|\((?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)
nhahtdh 正则表达式的稍短版本:
\(((?:[^()]++|(?R))*+)\)
您可以通过递归到整个表达式 ( (?R)
) 而不是子表达式 ( (?1)
) 来避免重复文字括号。否则是一样的。
用作:
my @list = $str =~ /\(((?:[^()]++|(?R))*+)\)/g;