I have a string and I would like to know the first position of a pattern. But it should be found only, if it’s not enclosed by with brackets.
Example String: “This is a (first) test with the first hit
“
I want to know the position of the second first
=> 32. To match it, the (first)
must be ignored, because it’s enclosed in brackets.
Unfortunately I do not have to ignore round brackets (
)
only, I have to ignore square brackets [
]
and brace brackets {
}
too.
I tried this:
preg_match(
'/^(.*?)(first)/',
"This is a (first) test with the first hit",
$matches
);
$result = strlen( $matches[2] );
It works fine, but the result is the position of the first match (11).
So I need to change the .*?
.
I tried to replace it with .(?:(.*?))*?
in the hope, all characters inside the brackets will be ignored. But this does not match the brackets.
And I can’t use negative look ahead '/(?<!()first(?!))/'
, since I have three different bracket types, which have to match open and closing bracket.
Advertisement
Answer
You can match all 3 formats that you don’t want using a group with and an alternation and make use of (*SKIP)(*FAIL) to not get those matches. Then match first
between word boundaries b
(?:(first)|[first]|{first})(*SKIP)(*FAIL)|bfirstb
Example code
$strings = [
"This is a (first) test with the first hit",
"This is a (first] test with the first hit"
];
foreach ($strings as $str) {
preg_match(
'/(?:(first)|[first]|{first})(*SKIP)(*FAIL)|bfirstb/',
$str,
$matches,
PREG_OFFSET_CAPTURE);
print_r($matches);
}
Output
Array
(
[0] => Array
(
[0] => first
[1] => 32
)
)
Array
(
[0] => Array
(
[0] => first
[1] => 11
)
)