You are not getting a match because in the pattern 123-(?!a[a-z]*)-456
the lookahead assertion (?!a[a-z]*)
is always true because after matching the first -
it has to directly match another hyphen like the pattern actually 123--456
If you move the last hyphen inside the lookahead like 123-(?!a[a-z]*-)456
you only get 1 match for 123-456
because you are actually not matching the middle part of the string.
Another option with php can be to consume the part that you don't want, and then use SKIP FAIL
^123-(?:a[a-z]*-(*SKIP)(*F)|\w+-)?456$
Explanation
^
Start of string
123-
Match literally
(?:
Non capture group for the alternation
a[a-z]*-(*SKIP)(*F)
Match a
, then optional chars a-z, then match -
and skip the match
|
Or
\w+-
Match 1+ word chars followed by -
)?
Close the non capture group and make it optional to also match when there is no middle part
456
Match literally
$
End of string
Regex demo
Example
$myStrings = array(
"123-456",
"123-7-456",
"123-Apple-456",
"123-0-456",
"123-Alphabet-456",
"123-b-456"
);
foreach($myStrings as $myStr) {
if (preg_match("/^123-(?:a[a-z]*-(*SKIP)(*F)|\w+-)?456$/i", $myStr, $match)) {
echo "Match for $match[0]" . PHP_EOL;
} else {
echo "No match for $myStr" . PHP_EOL;
}
}
Output
Match for 123-456
Match for 123-7-456
No match for 123-Apple-456
Match for 123-0-456
No match for 123-Alphabet-456
Match for 123-b-456