Регулярное выражение PHP с границей слова после экранированного символа

Недавно я наткнулся на эту проблему и не могу понять, почему это происходит.

Рассмотрим следующий пример: у меня есть случайный текст и массив с некоторыми языками программирования. В цикле я сопоставлю каждый язык как целые слова, используя регулярное выражение и с границами слов \ 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%, что этот подход не возымел бы обратный эффект.

Почему это происходит и что делать, чтобы получить нужный мне результат?

После символа + нет границы слова, поскольку + не является словесным символом.

anubhava 24.05.2018 18:41

Это действительно работает, @ wp78de. Я думал о (^|[^\w])C\+\+([^\w]|$), но ваше выражение более элегантное.

Caio Ferreira Silva 25.05.2018 14:49
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
2
72
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Рекомендуемый способ решить эту проблему - использовать поисковые пути для утверждения символов слов вместо границ, например (?<!\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/

Другие вопросы по теме