6

I currently have a regular expression to match where a string contains 'bar' but is not preceded by 'foo':

(?<!foo)bar

I wish to modify the regex to match where a string contains 'bar' but is not preceded by 'foo' and (optionally) any additional character(s).

EG. 'footestbar' should not match as bar is preceded by 'foo' followed by 'test'.

I cannot find a way to achieve this as regular expressions do not permit the use of a quantifier within a negative lookbehind. Subsequently I cannot do the following:

(?<!foo.*)bar

Is there an alternative approach?

UPDATE:
The regular expression flavour is re2. I am currently reviewing the documentation, but on first glance have noticed the following:

(?<!re)     after text not matching re (NOT SUPPORTED)

Therefore the solution cannot use a negative lookbehind (if I'm interpreting the documentation correctly).

Fitzroy
  • 331
  • "and (optionally) any additional character(s)" - what can precede it? Should it be at the beginning of a string, or at the beginning of a word? Also please specify which flavour of regex do you use, it might influence the answer. – Máté Juhász Feb 01 '16 at 10:27
  • I've just had confirmation that it is the re2 regular expression library: https://github.com/google/re2/wiki/Syntax

    I've just read that after text not matching is not supported:

    `(?<!re)  after text not matching re (NOT SUPPORTED)`
    
    – Fitzroy Feb 01 '16 at 12:01

1 Answers1

3

Amended Post

So it would seem that some (most?) Regex engines only work with a fixed length lookbehind. However, they seem fine to accept a variable length lookahead. I'm not sure what your use case for this is or how viable it would be, but one idea could be to reverse your string, and use:

rab(?!.*oof)

enter image description here

Of course, it looks ridiculous, and I don't know how your using it or how useful it will be. Most of my experience with Regex has been using .NET, and mostly not needed lookbehinds. Just an idea for you..!

Original Post - Only works with certain Regex engines (Tested using .NET)

Try the following regex:

(?<!foo(?:.*)?)bar

This adds an optional, non capturing group within the same negative look behind.

enter image description here

Jonno
  • 21,217
  • 4
  • 64
  • 71
  • Interesting. What flavour of regex did you test that against? I am using https://regex101.com and testing against pcre (php) and python and it doesnt work because "Lookbehinds need to be zero-width, thus quantifiers are not allowed". I didn't bother testing against javascript because I believe that negative lookbehinds are not supported. – Fitzroy Feb 01 '16 at 10:38
  • @Fitzroy This is using .NET regex, I'm not sure if that translates to a specific regex engine or is one in it's own right, I believe it is. I'll see if I can get something working on regex101. – Jonno Feb 01 '16 at 10:42
  • @Fitzroy Added an idea for you, whether you can use it or not I don't know because I don't know your use case. – Jonno Feb 01 '16 at 11:05
  • I'm unable to modify the content to which I'll be applying the regex. – Fitzroy Feb 01 '16 at 11:42
  • @Fitzroy I don't really know of any other ways then, sorry! – Jonno Feb 01 '16 at 11:43