В настоящее время я пишу библиотеку для соответствия определенным словам в контенте.
По сути, он работает, компилируя слова в регулярные выражения и запуская контент через указанные регулярные выражения.
Функция, которую я хочу добавить, указывает, должно ли заданное слово совпадать должно начинаться и / или заканчивать слово. Например, у меня есть слово 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);
Любые идеи, почему регулярное выражение делает это?
Мне бы просто понравилась страница, в которой четко указаны границы слов, я просто не могу найти ее для жизни.
Граница слова \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" }