我目前正在编写一个用于匹配内容中特定单词的库。
基本上它的工作方式是将单词编译成正则表达式,并通过所述正则表达式运行内容。
我要添加的功能是指定要匹配的给定单词是否必须开始和/或结束单词。例如,我有cat
这个词。我指定必须开始一个单词,因此catering
将匹配,因为cat
位于开头,但是ducat
不匹配,因为cat
没有开始这个词。
我想使用word boundaries执行此操作,但在某些测试中,我发现它无法正常工作。
采取以下措施,
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);
为什么正则表达式会这样做?
我只是爱一个页面,清楚地记录了如何确定单词边界,我找不到我的生活。
答案 0 :(得分:18)
单词边界\b
匹配从\w
(单词字符)到\W
非单词字符的变化。如果您的\b
字符@
之前有\W
,您希望匹配。因此,为了匹配,您需要在@
something@nimal
^^
==>由于g
和@
之间的单词边界而匹配。
something!@nimal
^^
==>不匹配,因为在!
和@
之间没有字边界,两个字符都是\W
答案 1 :(得分:2)
我遇到类似匹配时遇到的一个问题是像can't
和it's
这样的词,其中撇号被视为单词/非单词边界(因为它与{{1}相匹配而不是\W
)。如果这对您来说可能是一个问题,您应该排除撇号(以及有时出现的所有变体,如'和'),例如通过创建一个类,例如\w
。
你可能也会遇到UTF8字符的问题,这些字符确实是单词的一部分(即我们人类用单词表示的意思),例如测试你的正则表达式如何对[\b^']
这样的单词进行编码。
因此,在解析普通语言时,通常会更容易。要查找的文字"语言"边界,例如空格字符(不仅仅是字面上的空格,而是完整的类,包括换行符和制表符),逗号,冒号,句号等(如果要解析HTML,则使用斜括号)。 YMMV。
答案 2 :(得分:0)
@
不是单词字符的一部分(在您的语言环境中可能是这样,但默认 “单词”字符是任何字母或数字或下划线字符,Source - 因此@
不是word
字符,因此不是\w
而是\W
链接任何\w\W
或\W\w
组合标记\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"
}
输出:
{{1}}