IT技术博客大学习 共学习 共进步

PHP正则之递归匹配

风雪之隅 2011-10-14 13:49:04 浏览 3,604 次

我记得早前有同事问, 正则是否能处理括号配对的正则匹配.

比如, 对于如下的待匹配的字符串:

   ((())

就是一个括号配对的字符串. 而对于如下的待匹配字符串:

   (((

则不是一个括号配对的字符串.

在以前, 这种情况, 正则无法处理, 最多只能处理固定层数的递归, 而无法处理无线递归的情况… 而在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提供的帮助 :)

建议继续学习

  1. PHP与递归Recursion (阅读 9,124)
  2. grep 正则表达式选项要记得转义 (阅读 6,443)
  3. 统计最近用过的linux命令 (阅读 6,403)
  4. 正则表达式基础 (阅读 6,161)
  5. 正则表达式的与或非 (阅读 5,743)
  6. 循环、迭代、遍历和递归 (阅读 5,423)
  7. 学习Grep,Sed中的正则 (阅读 5,265)
  8. URL正则表达式 (阅读 4,662)
  9. 正则表达式简要入门 (阅读 4,363)
  10. 正则转义符汇总 (阅读 4,321)