- 本文地址: https://www.laruence.com/2011/09/30/2179.html
- 转载请注明出处
我记得早前有同事问, 正则是否能处理括号配对的正则匹配.
比如, 对于如下的待匹配的字符串:
((()))
就是一个括号配对的字符串. 而对于如下的待匹配字符串:
((()
则不是一个括号配对的字符串.
在以前, 这种情况, 正则无法处理, 最多只能处理固定层数的递归, 而无法处理无线递归的情况... 而在perl 5.6以后, 引入了一个新的特性: Recursive patterns, 使得这种需求可以被正确的处理.
Recursive pattern引入了一个新的符号(?R), 这个符号可以表示: 正则模式本身, 比如:
#1(?R)*#
我们来仔细看一下, 这个正则, 首先它匹配数字"1", 然后(?R)*表示, 正则式本身, 也就是说, 可以认为是:
#1(正则本身(正则本身).....)*#
于是, 对于文章开头说到的情况:"括号配对", 可以写下如下的正则式:
#\((?R)*\)#
就可以正确处理.
这里提醒一下, 用的时候, 要注意一定要给递归一个截至条件, 比如如果上面的例子写成:
#1(?R)#
那么, 就不会正常工作, 因为这个展开以后表示要匹配无限多个"1", 所以在上面的例子中, 写作了(?R)*, 让它可以有一个截止的条件(可以为0个).
另外, 这个新特性也支持序号引用(?index), 比如:
#(1)(2)(3)(?3)(?2)(?1)#
表示匹配, 123321.
如果想更多的了解这个新特性, 可以参看: http://www.php.net/manual/en/regexp.reference.recursive.php
感谢windy, 和shiwei提供的帮助 🙂
[…] *(?R)递归的正则匹配,表达正则模式自身,PHP正则之递归匹配 ,匹配的是一个str(str(str()))的形式.函数套函数不能有参数 […]
[…] PHP正则之递归匹配 […]
[…] 本文地址: http://www.laruence.com/2011/09/30/2179.html […]
看到这里我想到一个问题:
如何匹配连续递增的3个数。比如:从字符串’123221234′ 中匹配出123/123/234。
我用这种方式过滤html空标签,好像没效果呢
::
]+>((\s| )+|(?R))*
如果是什么地方错了请帮忙指点下。
正则也递归。。。学习了~~
什么时候能支持平衡组呢?
这个问题我一直纠集,我知道?R可递归匹配,但我的问题是,如果“递归”匹配a(b(c(d(e)))),注意,前面的a是必须的,我试过了很多办法,没法达到目的。
请问下,我说的这个问题能解决吗?(不是硬性匹配,是递归,要有通用性)
[…] http://www.laruence.com/2011/09/30/2179.html PHP正则之递归匹配 […]
《正则表达式30分钟入门教程》中也有一个例子,讲的也是括号匹配。
[…] 本文地址: http://www.laruence.com/2011/09/30/2179.html […]
有错字。无限递归打成了无线递归
@CFC4N 恩, 有可能, 不过我是最近才发现的, 惭愧, 🙂
PHP的正则递归(又称迭代)这个特性,在5.2版本已经支持了吧。不清楚5.2的版本用的是PCRE那个版本。最早是php的版本支持的不清楚。是不是PHP5就开始支持了?
我觉得这种递归匹配字符串的事情,最好不要用正则去实现,尽量程序+算法实现,正则去做的话,回溯太多了,很容易引起 回溯太多,引爆了堆栈,类似http://www.laruence.com/2010/06/08/1579.html 这里的问题。