- URL: https://www.laruence.com/en/2011/09/30/2179.html
- Please include attribution when republishing.
I remember a colleague asking me a while ago: can a regex handle matching paired brackets?
For example, for the following string to be matched:
((()))
this is a string of paired brackets. Whereas for the following string:
((()
it is not a string of paired brackets.
In the past, a regex could not handle this kind of case — at best it could only handle recursion of a fixed depth, and could not handle unbounded recursion... But after perl 5.6, a new feature was introduced: Recursive patterns, which makes this kind of requirement possible to handle correctly.
Recursive patterns introduced a new symbol (?R). This symbol can represent the regex pattern itself. For example:
#1(?R)*#
Let's look at this regex carefully. First it matches the digit "1". Then (?R)* means the pattern itself, i.e. it can be thought of as:
#1(the pattern itself (the pattern itself).....)*#
So, for the "paired brackets" case mentioned at the beginning, we can write the following regex:
#\((?R)*\)#
and it will handle it correctly.
A reminder: when using it, be careful to always give the recursion a terminating condition. For example, if the example above were written as:
#1(?R)#
it would not work correctly, because when expanded it means matching an unlimited number of "1"s. So in the example above it was written as (?R)*, allowing it to have a terminating condition (it can be zero occurrences).
Also, this new feature also supports numbered references (?index). For example:
#(1)(2)(3)(?3)(?2)(?1)#
means matching 123321.
If you want to learn more about this feature, see: http://www.php.net/manual/en/regexp.reference.recursive.php
Thanks to windy and shiwei for their help 🙂
Be First to Comment