Я считаю, что самый простой и описательный способ сделать это - использовать негативные взгляды и взгляды назад.
См:
preg_match_all('/(?<![^\s])!!\d{3}(?![^\s])/', '!!333 !!333!!333 !!333 test !!333', result);
Это говорит: сопоставьте что-нибудь в форме !! [0-9] [0-9] [0-9], у которой нет ничего кроме пробела впереди или позади него Обратите внимание, что эти lookaheads / lookbehind сами по себе не совпадают, они являются «утверждениями нулевой ширины», они отбрасываются, и поэтому вы получаете только «!! 333» и т. Д. В своем совпадении, а не «!! 333» и т. Д.
Возвращает
[0] => Array
(
[0] => !!333
[1] => !!333
[2] => !!333
)
)
Также
preg_match_all(
'/(?<![^\s])!!\d{3}(?![^\s])/',
'!!333 !!555 !!333 !!123 !!555 !!456 !!333 !!333 !!444 !!444 !!123 !!123 !!123!!123',
$result));
возвращает
[0] => Array
(
[0] => !!333
[1] => !!555
[2] => !!333
[3] => !!123
[4] => !!555
[5] => !!456
[6] => !!333
[7] => !!333
[8] => !!444
[9] => !!444
[10] => !!123
[11] => !!123
)
То есть все, кроме двух последних, слишком длинные.
См. Учебник Lookahead .