Как использовать PHP для поиска в строке слов, начинающихся/заканчивающихся специальными символами регулярного выражения?

Я использую PHP, чтобы узнать, встречается ли строка, начинающаяся со специального символа регулярного выражения, как слово в текстовой строке. Это PHP-код:

$subject = " hello [hello [helloagain ";
$pattern = preg_quote("[hello");
if (preg_match("/\b" . $pattern  . "\b/", $subject, $dummy)) { 
    echo "match";
} else {
    echo "no match";
}

Шаблон начинается с символа [, поэтому для его экранирования используется preg_quote(). В теме есть экземпляр [hello как слово, поэтому должно быть одно совпадение, но вышеприведенная функция preg_match() не возвращает совпадений. Думаю причина в том, что в теме спецсимвол не распознается как начало или конец слова, но никак не могу придумать обходного пути, есть идеи? Спасибо.


person user646234    schedule 15.03.2012    source источник


Ответы (2)


Вы правы, что граница слова не будет совпадать между пробелом и символом [.

Вместо использования границы слова вы можете явно искать пробелы (и другие разделители, такие как запятые и точки, если хотите) до и после слова:

if (preg_match("/(\s|^)" . $pattern  . "(?=\s|$)/", $subject, $dummy)) { 
person Mark Byers    schedule 15.03.2012
comment
Большое спасибо. Это решило эту проблему, хотя я бы предпочел не перечислять все возможные разделители. Мне также нужно подсчитать количество вхождений шаблона в тему. Я попробовал ваше решение на слегка измененной теме следующим образом: $subject = " hello [hello [hello [helloagain "; $pattern = preg_quote("[hello"); echo preg_match_all("/(\s|^)" . $pattern . "(\s|$)/", $subject, $dummy); preg_match_all() возвращает 1, а не 2 (теперь в теме два экземпляра ‹i›[hello‹/i›, разделенные одним пробелом), почему ? - person user646234; 16.03.2012
comment
@ user646234: совпадения регулярных выражений не могут перекрываться. Чтобы решить эту проблему, используйте просмотр вперед. Я обновил ответ. Примечание для дальнейшего использования: если вы сформулируете свои полные требования в начале, вы получите более точные ответы. - person Mark Byers; 16.03.2012

Если я правильно понимаю вопрос, вы можете просто использовать strpos() с начальным пробелом разделить слова:

$subject = " hello [hello [helloagain ";
$pattern = " [hello";

if(strpos($subject, $pattern) !== FALSE)
  // ...
else
  // ...

Я думаю, что не использовать регулярное выражение здесь на самом деле лучший метод, так как вы ищете специальные символы регулярного выражения, и их не нужно экранировать, если вы используете strpos().

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

person Jon Egeland    schedule 15.03.2012
comment
Спасибо. Как указано в моем комментарии к Mark_Byers выше, мне также нужно подсчитать количество вхождений шаблона в виде слова, поэтому я решил использовать регулярные выражения. - person user646234; 16.03.2012