[英]How exactly do Regular Expression word boundaries work in PHP?
我目前正在编写一个用于匹配内容中特定单词的库。
本质上,它的工作方式是将单词编译成正则表达式,并通过所述正则表达式运行内容。
我要添加的一个功能是指定要匹配的给定单词是否必须开始和/或结束一个单词。 例如,我有单词cat
。 我指定它必须以一个单词开头,因此catering
将匹配为cat
开头,但ducat
不匹配,因为cat
不以该单词开头。
我想使用word boundary来做到这一点,但在一些测试中我发现它不像我期望的那样工作。
采取以下措施,
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
以匹配 rest (它应该)。 相反,它似乎结合了!
和@
一起组成一个词,通过以下匹配确认,
preg_match("/g\b!@\bn/i", "something!@nimal", $match);
任何想法为什么正则表达式会这样做?
我只是喜欢一个清楚地记录单词边界是如何确定的页面,我只是找不到适合我一生的页面。
单词边界\b
匹配从\w
(单词字符)到\W
非单词字符的变化。 如果在您的@
之前有一个\b
是一个\W
字符,那么您想要匹配。 所以要匹配你的@
之前需要一个单词字符
something@nimal
^^
==> 由于g
和@
之间的单词边界而匹配。
something!@nimal
^^
==> 不匹配,因为在!
和@
没有字边界,两个字符都是\W
我在进行类似匹配时遇到的一个问题是can't
和it's
类的词,其中撇号被视为单词/非单词边界(因为它与\W
而不是\w
匹配)。 如果这对您来说可能是个问题,您应该排除撇号(以及有时出现的所有变体,例如 ' 和 '),例如通过创建 class 例如[\b^']
。
您可能还会遇到真正属于单词的 UTF8 字符(即我们人类对单词的意思)的问题,例如,针对您对Svašek
类的单词进行编码的方式测试您的正则表达式。
因此,在解析普通“语言”文本时,通常更容易查找“语言”边界,例如空格字符(不仅仅是字面上的空格,而是完整的 class,包括换行符和制表符)、逗号、冒号、句号等(以及如果您正在解析 HTML,则使用尖括号)。 YMMV。
@
不是单词字符的一部分(在您的语言环境中,它可能是,但是,默认情况下,“单词”字符是任何字母或数字或下划线字符, Source -所以@
不是word
字符,因此不是\w
而是\W
和链接的任何\w\W
或\W\w
组合标记 a \b
position ),因此它始终是匹配的单词边界(在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);
Output:
int(0)
array(0) {
}
int(1)
array(2) {
[0]=>
string(6) "animal"
[1]=>
string(6) "animal"
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.