Rene Jorgensen
Rene Jorgensen

Reputation: 179

How do I design a pattern that only captures strings without certain character combinations?

I'm struggling with regex lookaheads and all the tutorials I can find are for password checks and not for certain character combinations.

Here's a problem I don't understand which describes my struggle with this part of regex:

$string1 = 'I have a yellow engine, I have a black engine';
$string2 = 'I have a yellow engine, I have a red engine';
$string3 = 'I have a red engine, I have a black engine';

$pattern = '~I.*?(?!.*(red|green|blue)).*?engine~';

$preg_match_all($pattern, $string[1-3], $matches);

$string1 matches correctly:

0 => "I have a yellow engine"
1 => "I have a black engine"

$string2 matches the entire string and $string3 matches similar to $string1.

How do I design a pattern that only captures strings ('I have a [colour] engine') without certain colours?

Upvotes: 3

Views: 38

Answers (1)

Kasravnd
Kasravnd

Reputation: 107347

The .* after your negative look-ahead will match everything and actually will destroy the effect of the look-ahead. You can simply use following regex:

I\s(?:(?!(red|green|blue)).)*engine

Demo: https://regex101.com/r/tO9nC5/1

Note that you even don't need .* inside the look-ahead, because you have a * out of it which makes it to match every length of string.

Also note that if you want to prevent your regex to match strings like following:

I have everything I don't engine

In fact if you want to match the inner I before engine you better to add I to the list of forbidden words:

I\s(?:(?!(I|red|green|blue)).)*engine

Upvotes: 2

Related Questions