I have a possibly large block of text to search for instances of [[...]]
, where the ...
can be anything, including other brackets (though they cannot be nested; the first instance of ]]
after [[
ends the match).
I can think of two ways to match this text:
/\[\[.+?\]\]/
/\[\[(?:(?!\]\]).)+\]\]/
Is one choice inherently better than the other, from a performance standpoint (I'd say the first is probably more readable)? I recall reading that it's better not to use non-greedy qualifiers, but I cannot find a source for that now.
It is better to use a non-greedy quantifier in this case.
Take this example string "[[a]b]]"
Non-greedy quantifier
\[\[.+?\]\] Atom # 1 2 3 4 5
\[
matches\[
matches.+?
matches the "a"
\]
matches\]
fails, back to #3 but keep string position.+?
matches the "]"
\]
fails, back to #3 but keep string position.+?
matches the "b"
\]
matches\]
matchesLook-ahead:
\[\[(?:(?!\]\]).)+\]\] Atom # 1 2 3 4 5 6 7
\[
matches\[
matches(?!\]\])
succeeds (i.e. non-match) immediately at "a"
, go on.
matches the "a"
, repeat at #3(?!\]\])
achieves partial match at "]"
(?!\]\])
succeeds (i.e. non-match) at "b"
, go on.
matches the "]"
, repeat at #3(?!\]\])
succeeds (i.e. non-match) immediately at "b"
, go on.
matches the "b"
, repeat at #3(?!\]\])
achieves partial match at "]"
(?!\]\])
achieves full match at "]"
, ergo: #4 fails, exit #3\]
matches\]
matchesSo it looks like the non-greedy quantifier has less work to do.
Disclaimer: This is an artificial example and real-life performance may differ, depending on the input, the actual expression and the implementation of the regex engine. I'm only 98% sure that what I outlined here is what is actually happening, so I'm open for corrections. Also, as with all performance tips, don't take this at face value, do your own benchmark comparisons if you want to know for sure.
Another variant: /\[\[((?:\]?[^]])+)]]/
It uses neither non-greedy quantifiers nor look-aheads. It allows a single ]
before any non-]
. If there would be two ]
in sequence, the inner repetition would stop, and and the match would end.
This pattern would be best to use with FSA-compiling regex engines. On back-tracking engines, it could get slower than the non-greedy variant.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With