PHP регулярное выражение с границей слова после экранированного символа - PullRequest
0 голосов
/ 24 мая 2018

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

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

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

1 Ответ

0 голосов
/ 24 мая 2018

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