John
John

Reputation: 1591

Regex matching the first instance

I have a regex (.*)?start((?!(foo|boo)).)* end test.*.

What it does is it will return true if there is no foo or boo in between start and end test and false otherwise. It is working as expected. But I am facing issue with the below expression

start foo again start too anything anything end test

My expected result is false because foo is there in between. But looks like it is not taking the first start.

Upvotes: 0

Views: 70

Answers (2)

Allan
Allan

Reputation: 12438

Tim Biegeleisen answer is great but it does not accept strings in which start and end test are not present (example: abc123 should be accepted as the condition there is no foo or boo in between start and end test is respected) . It is not obvious from your question if you need those strings or not. If you do then, you have to change the regex into:

 ^(?:(?!\bstart\b).)*\bstart\b(?:(?!\b(foo|boo)\b).)*\bend test\b.*$|^(?:(?!\bstart\b).)*$|^(?:(?!\bend test\b).)*$

Demo: https://regex101.com/r/492Z5m/2/

Upvotes: 2

Tim Biegeleisen
Tim Biegeleisen

Reputation: 521249

Consider using this pattern:

^(?:(?!\bstart\b).)*\bstart\b(?:(?!\b(foo|boo)\b).)* end test\b.*$

The reason your current regex is failing is that the initial (.*)?start is actually consuming start foo again, hence getting around the negative lookahead tempered dot which checks that foo and boo do not appear in between. My approach consumes at the beginning only if the word be not start. This lets your logic work as expected, and we can assert that neither foo nor boo appear in between the very first start and the end test text.

Note that I added word boundaries in a few places, and also made the groups non capturing, assuming you don't want to capture anything.

Demo

Upvotes: 2

Related Questions