正则expression式字边界在PHP中如何工作?

我目前正在编写一个库来匹配内容中的特定单词。

本质上,它的工作方式是将单词编译为正则expression式,并通过所述正则expression式运行内容。

我想要添加的function是指定给定的单词是否必须开始和/或结束一个单词。 例如,我有cat这个词。 我指定它必须开始一个单词 ,所以catering cat在一开始相匹配 ,但由于cat不启动单词, ducat 将不匹配

我想用字界来做到这一点,但在一些testing中,我发现它并不像我预期的那样工作。

采取以下措施,

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

在上面的陈述中,我会期待以下结果,

 > false > 1 (@nimal) 

但结果却相反,

 > 1 (@nimal) > false 

首先,我会期望它会因为小组吃掉@而失败,只剩下与@nimal匹配,这显然不是。 相反,组匹配一个空string,所以@nimal被匹配,意味着@被认为是该词的一部分。

第二,我期望这个小组吃掉! 留下@nimal匹配其余(应该))。 相反,它似乎结合了!@一起形成一个单词,经以下匹配确认,

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

任何想法为什么正则expression式这样做?

我只是喜欢一个页面,清楚地logging了单词界限是如何确定的,我只是找不到一个为我的生活。

单词边界\b匹配从\w (单词字符)到\W非单词字符的变化。 如果您的@\W字符之前有一个\b ,则要匹配。 所以要匹配你需要一个单词字符在你的@

 something@nimal ^^ 

==>由于g@之间的单词边界匹配。

 something!@nimal ^^ 

==>没有匹配,因为之间!@没有字边界,两个字符都是\W

我遇到的一个类似的匹配问题是类似于can't的单词,撇号被认为是单词/非单词边界(因为它与\W匹配而不是\w )。 如果这对您可能是一个问题,您应该排除撇号(以及所有变体,如有时出现的“和”),例如通过创build一个类,例如[\b^']

你可能也会遇到UTF8字符的问题,这些字符是真正属于这个词的一部分(也就是我们人类的意思),比如testing你的正则expression式,比如Svašek

因此,当分析正常的“语言”文本以查找诸如空间字符(不仅仅是字面上的空格,而是包括换行符和制表符的完整类),逗号,冒号,句号等(和如果您正在parsingHTML,则使用尖括号)。 因人而异。

@不是单词字符的一部分(在你的语言环境中,可能它是,但是, 默认情况下 ,“单词”字符是任何字母或数字或下划线字符 , 来源 – 所以@不是一个word字符,因此不\w\W和作为链接任何\w\W\W\w组合标记一个\b 位置 ),因此它总是匹配的字边界(在OP的正则expression式)。

以下类似于您的正则expression式,不同之处在于使用的不是@ 。 行的开始也是一个字的边界,所以不需要指定它:

 $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" }