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