Недавно я наткнулся на эту проблему и не могу понять, почему это происходит.
Рассмотрим следующий пример: у меня есть случайный текст и массив с некоторыми языками программирования. В цикле я сопоставлю каждый язык как целые слова, используя регулярное выражение и с границами слов \ b до и после, а затем распечатаю URL-адрес.
$string = 'I don\'t know C e C++ so well, but I can code in PHP.';
$languages = [
'PHP' => '/php/',
'C++' => '/cpp/',
'C' => '/c/',
];
foreach ($languages as $name => $uri) {
$regex = '/\b' . preg_quote($name, '/') . '\b/';
if (preg_match($regex, $string)) {
echo "For {$name} information refer to http://foo.bar{$uri}" . PHP_EOL;
}
}
Я ожидал бы следующего результата:
For PHP information refer to http://foo.bar/php/
For C++ information refer to http://foo.bar/cpp/
For C information refer to http://foo.bar/c/
Однако результат, который я получаю:
For PHP information refer to http://foo.bar/php/
For C information refer to http://foo.bar/c/
Граница слова (\ b) сразу после экранированного знака плюс (+) работает не так, как я ожидал.
Если я заменю этот \ b на [^ \ w], он сработает, но я не уверен на 100%, что этот подход не возымел бы обратный эффект.
Почему это происходит и что делать, чтобы получить нужный мне результат?
Это действительно работает, @ wp78de. Я думал о (^|[^\w])C\+\+([^\w]|$), но ваше выражение более элегантное.






Рекомендуемый способ решить эту проблему - использовать поисковые пути для утверждения символов слов вместо границ, например (?<!\w)c\+\+(?!\w):
$string = 'I don\'t know C e C++ so well, but I can code in PHP.';
$languages = [
'PHP' => '/php/',
'C++' => '/cpp/',
'C' => '/c/',
];
foreach ($languages as $name => $uri) {
$regex = '/(?<!\w)' . preg_quote($name, '/') . '(?!\w)/';
if (preg_match($regex, $string)) {
echo "For {$name} information refer to http://foo.bar{$uri}" . PHP_EOL;
}
}
Выход:
For PHP information refer to http://foo.bar/php/
For C++ information refer to http://foo.bar/cpp/
For C information refer to http://foo.bar/c/
После символа
+нет границы слова, поскольку+не является словесным символом.