Как точно работают границы слова регулярного выражения в PHP?

В настоящее время я пишу библиотеку для соответствия определенным словам в контенте.

По сути, он работает, компилируя слова в регулярные выражения и запуская контент через указанные регулярные выражения.

Функция, которую я хочу добавить, указывает, должно ли заданное слово совпадать должно начинаться и / или заканчивать слово. Например, у меня есть слово cat . Я указываю, что он должен начинать слово , поэтому catering будет соответствовать, поскольку cat находится в начале, но ducat не будет соответствовать, так как cat не запустит слово.

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

Возьмите следующее:

 preg_match("/(^|\b)@nimal/i", "something@nimal", $match); preg_match("/(^|\b)@nimal/i", "something!@nimal", $match); 

В приведенных выше утверждениях я ожидал бы следующих результатов:

 > false > 1 (@nimal) 

Но результат вместо этого противоположный,

 > 1 (@nimal) > false 

Во-первых, я ожидаю, что он потерпит неудачу, так как группа будет есть @ , оставив nimal в соответствии с @nimal , что, очевидно, это не так. Вместо этого группа соответствует пустой строке, поэтому @nimal сопоставляется, что означает, что @ считается частью слова.

Во втором, я бы ожидал, что группа съест ! оставляя @nimal для соответствия остальным (что должно). Вместо этого, похоже, это сочетание ! и @ вместе, чтобы сформировать слово, что подтверждается следующим сопоставлением,

 preg_match("/g\b!@\bn/i", "something!@nimal", $match); 

Любые идеи, почему регулярное выражение делает это?

Мне бы просто понравилась страница, в которой четко указаны границы слов, я просто не могу найти ее для жизни.

Related of "Как точно работают границы слова регулярного выражения в PHP?"

Граница слова \b совпадает с изменением от символа \w (символ слова) на символ \W а не на слово. Вы хотите совместить, если есть \b перед вашим @ который является символом \W Таким образом, чтобы соответствовать, вам нужен символ слова перед вашим @

 something@nimal ^^ - something@nimal ^^ 

==> Матч из-за границы слова между g и @ .

 something!@nimal ^^ - something!@nimal ^^ 

==> НЕТ, потому что между ! и @ нет границы слова, оба символа \W

Одна из проблем, с которыми я столкнулся, делает подобное сопоставление – это слова типа « can't и « it's , где апостроф считается границей слов / не-слов (поскольку он сопоставляется с \W а не \w ). Если это может быть проблемой для вас, вы должны исключить апостроф (и все варианты, такие как «и», которые иногда появляются), например, путем создания класса, например [\b^'] .

Возможно, у вас также могут возникнуть проблемы с символами UTF8, которые действительно являются частью слова (то есть, что мы, люди, понимаем под словом), например, проверим ваше регулярное выражение на то, как вы кодируете такое слово, как Svašek .

Поэтому часто бывает проще при анализе обычного «лингвистического» текста искать «лингвистические» границы, такие как символы пробела (не просто буквально пробелы, а полный класс, включая новые строки и вкладки), запятые, двоеточия, полные остановки и т. Д. (И угловые скобки, если вы разбираете HTML). YMMV.

@ не является частью символа слова (в вашей локали, вероятно, это, однако, по умолчанию символ «слово» – это любая буква или цифра или символ подчеркивания , источник – поэтому @ не является символом word , поэтому не \w но \W и как связанная любая комбинация \w\W или \W\w отмечает a \b позицию ), поэтому всегда совпадает граница слова (в регулярном выражении OP).

Следующее похоже на ваши регулярные выражения с той разницей, что вместо @ используется a . И начало строки также является границей слов, поэтому нет необходимости указывать ее также:

 $r = preg_match("/\b(animal)/i", "somethinganimal", $match); var_dump($r, $match); $r = preg_match("/\b(animal)/i", "something!animal", $match); var_dump($r, $match); 

Вывод:

 int(0) array(0) { } int(1) array(2) { [0]=> string(6) "animal" [1]=> string(6) "animal" }