正则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" }