0

我在 php 中使用 preg_match_all 从用 DSL 编写的字符串构造标记。当我将测试字符串硬编码到我的 PHP 代码中并运行它时,一切正常。但是,当我从数据库中读取相同的字符串时,它匹配前两个标记,然后字符串的其余部分作为一个标记匹配,此时它显然应该分成多个子单元,就像字符串被硬编码时所做的那样。

怎么会这样?

我在正则表达式中使用 .+ 来匹配“其余部分”。基本上我的 DSL 由关键字和其余部分组成,所以我的 preg_match_all 正则表达式如下所示:

/(?P<NameOfKeyword1>Keyword1)|(?P<NameOfKeyword2>Keyword2)|(?P<NameOfKeyword3>Keyword3)|(?P<Linebreak>\\v+)|(?P<Rest>.+(?=Keyword1)|.+(?=Keyword2)|.+(?=Keyword3)|.+)/

基本上我首先匹配关键字,然后匹配换行符,然后是其余的,直到出现下一个关键字(或换行符或字符串结尾)。

那么为什么当字符串被硬编码时它会正确匹配,但从数据库中读取相同的字符串时却不匹配呢?

从数据库中读取匹配为一个标记的其余字符串时,不应将其匹配为一个标记,因为它之间有关键字。看起来它匹配它基于 .+

编辑:我用于 preg_match_all 的标志是 PREG_SET_ORDER 和 PREG_OFFSET_CAPTURE

4

1 回答 1

1
(?P<Rest>.+(?=Keyword1)|.+(?=Keyword2)|.+(?=Keyword3)|.+)

这并不意味着“然后剩下的,直到出现下一个关键字(或换行符或字符串结尾)。 ”。事实上,除了新线之外,它永远不会停止。
为什么?您正在使用前瞻。基本上,.(?=Keyword1)意思是“任何字符后跟 Keyword1”(+它只是表示“一系列字符,每个字符后跟 Keyword1”)。
所以那些几乎不会匹配任何东西。最后.+是其余部分完全匹配的原因。

现在,如果你让他们变得懒惰,这应该有预期的输出:

(?P<Rest>.+?(?=Keyword1|Keyword2|Keyword3|$))

编辑:
还应该检查 \v:

/(?P<NameOfKeyword1>Keyword1)
|(?P<NameOfKeyword2>Keyword2)
|(?P<NameOfKeyword3>Keyword3)
|(?P<Linebreak>\v+)
|(?P<Rest>.+?(?=Keyword1|Keyword2|Keyword3|\v|$))/
于 2013-04-23T07:41:43.820 回答