繁体   English   中英

正则表达式字边界在 PHP 中究竟是如何工作的?

[英]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'tit'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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM