Regex ungreedy on the left side (i.e. the narrowest match on both sides)

Let's say I'm trying to match /dog.*lab/this text:

"I have a dog. My dog โ€‹โ€‹is a black laboratory. It was created in a laboratory."

Tough, it will fit "a dog. My dog โ€‹โ€‹is a black laboratory. It was created in a laboratory."

I want to find matches that are narrowest on both sides. If I use the ungreedy modifier, for example, /dog.*?lab/or /dog.*lab/Uit will be smaller, but still too much:
"Dog. My dog โ€‹โ€‹is a black laboratory"

Is there a way to make my search jagged on the left too, thus matching only โ€œdog is a black labโ€?

Many thanks. Sorry for the far-fetched example.

+5
source share
3 answers

You can use a forward-looking statement that eliminates the occurrence dogbetween dogand lab:

/dog(?:(?!dog).)*?lab/
+10
source

This works for me:

$str = "I have a dog. My dog is a black lab. He was created in a laboratory.";
if(preg_match('/.*(dog.*?lab)/',$str,$m)) {
    var_dump($m);
}
+2
source

The idea may be to try to use a negative character set, for example [^.!?], that will match all characters except ., ?and !, and therefore you can be sure that it is within the same sentence:

$string = "I have a dog. My dog is a black lab. He was created in a laboratory.";
preg_match('/dog[^.!?]*?lab/', $string, $match);
echo $match[0]; // Echoes "dog is a black lab"
+1
source

All Articles