我在php中使用preg_match_all从DSL中编写的字符串构造标记。当我将测试字符串硬编码到我的PHP代码中并运行它时,一切正常。但是,当我从数据库中读取相同的字符串时,它匹配前两个令牌,然后字符串的其余部分匹配为一个令牌,当它显然应该被分成多个子单元时,就像字符串被硬编码时一样。 / p>
这怎么可能?
我在正则表达式中使用。+来匹配“其余”。基本上我的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
答案 0 :(得分:1)
(?P<Rest>.+(?=Keyword1)|.+(?=Keyword2)|.+(?=Keyword3)|.+)
这并不意味着“然后其余的直到下一个关键字(或换行符或字符串结尾)出现。”。它实际上永远不会停止,除了新的线路
为什么?你正在使用前瞻。基本上,.(?=Keyword1)
表示“跟随Keyword1的任何字符”(+
只表示“一系列字符,每个字符后跟Keyword1”。)
所以那些不会与任何东西匹敌。最后.+
是剩下的完全匹配的原因。
现在,如果你制作它们lazy,这应该有预期的输出:
(?P<Rest>.+?(?=Keyword1|Keyword2|Keyword3|$))
修改强>
还应该检查\ v:
/(?P<NameOfKeyword1>Keyword1)
|(?P<NameOfKeyword2>Keyword2)
|(?P<NameOfKeyword3>Keyword3)
|(?P<Linebreak>\v+)
|(?P<Rest>.+?(?=Keyword1|Keyword2|Keyword3|\v|$))/