3 ms·
I'm pretty sure you can emulate the absent operator with look-ahead expressions. Untested: (?=((?!exp).)*$) That is: a zero-width assertion where at every char
by perlgeek 10y ago
I'm pretty sure you can emulate the absent operator with look-ahead expressions. Untested: (?=((?!exp).)*$)
That is: a zero-width assertion where at every character until the end exp doesn't match.
It's a nice idea to include this in the standard, and also illustrates how convoluted regular expression syntax has become over the years, mostly because it wasn't designed to be extensible.
- runako 10y agoI haven't completely ingested this post yet, but this seems to be incorrect: > I'm pretty sure you can emulate the absent operator with look-ahead expressions. Untested: (?=((?!exp).)*$) From TFA: "Note that this is not the same as a negative look-behind or look-ahead — we’ll see how shortly."
- perlgeek 10y agoWell, it's not the same as a simple positive or negative look-ahead, but that's not what I proposed either.
- falsedan 10y agoThe article explains that (?~foo) is not the same as (?!foo), since the latter fails the match if it matches, but the former succeeds if it can match anything that's not 'foo' (including 'oo'). The first examples anchor the patterns, so that this behaviour: "foo" ~= /(?~foo)/ # => 1 isn't revealed.
- al2o3cr 10y agoSee also the second comment on the original issue: https://bugs.ruby-lang.org/issues/5588 https://bugs.ruby-lang.org/issues/5588
- rntz 10y agoYou propose: (?=((?!exp).)*$) I don't believe you're right, but can't be sure, because you haven't given a method of translating an arbitrary regular expression containing a negation (?~E) into one without. For example, how would you translate: (?~exp)a.* which asks for "anything not exp, then an `a`, then anything"? (?=((?!exp).)*$).*a.* is wrong, since it doesn't match "aexp". (?=((?!exp).)*$)a.* is also wrong, for the same reason. (?=((?!exp).)*a)a.* is wrong, because it doesn't match "expba". EDIT: argh, HN formatting rules about asterisks.
- mnarayan01 10y agoI believe he's saying you'd want: (?=((?!exp).)*a.*) I'm a little dubious that full equivalence is maintained (particularly w.r.t. to e.g. #match), but my brain isn't up to handling convoluted REs this early. Edit: Another hangup I have is how would you do something like: ((?~E1)|E2)E3 Obviously you can distribute by duplicating E3, but then it's pretty clear what the absent operator buys you.
- rntz 10y ago(?=((?!exp).)*a.*) is also wrong; it doesn't match "expba", but (?~exp)a.* does.
- mnarayan01 10y ago/(?=((?!exp).)*a.*)/ =~ "expba" # => 1 for me at least (using #match is also truthy, but the matched string is not what I'd guess the absent operator would give).
- rntz 10y agoHuh! Now I am super confused.