为什么这种消极的前瞻不起作用?

时间:2019-04-25 19:19:47

标签: regex pcre

我有这个正则表达式,可以帮助我查找和替换不推荐使用的mysql查询。但是由于某种原因,一旦我替换了一个查询,它将重新捕获相同的区域,而只是将其扩展到下一个已弃用的查询的末尾。我试图通过不让它选择替换字符串(stmt)中的特定关键字来解决此问题,但是由于某种原因它忽略了此约束。

\(?mis)\$(?<sql>[a-z0-9]*) = (?<query>"select.*?\;)(?:(?!stmt).*?)\$(?<res>[a-z0-9]*?) = mysql_query.*?\;(?<txt>.*?)while\s?\(\$(?<row>[a-z0-9]*?) = mysql.*?\{\ 1

Here is the Regex101 I'm using to debug.

(?:(?!stmt).*?)是有问题的前瞻。我希望它允许在命名的捕获组之前和之后的任意数量的文本。 2 *?应该已经强迫它找到最小的部分。正如您在下面看到的,从第14行($sql = "SELECT admin from user where id=" . $userID;)开始有一个完全可以接受的比赛,但是它坚持要从顶部开始,一直到已经替换的旧比赛。

为什么我的消极前瞻没有按照我认为的方式工作? 3


enter image description here


1.我使用(?mis)是因为PHPStorm在正常标志下不能很好地发挥作用。
2.防止随机代码和错误的格式妨碍模式
3.如果这是一个XY问题,并且我应该以其他方式强制正确匹配,那么我欢迎您回答。

1 个答案:

答案 0 :(得分:1)

否定的前瞻不匹配是因为它不匹配。当<query>末尾的分号后紧跟“ stmt”时,它会拒绝匹配,这在您的代码中不是这种情况:后跟换行符,空格,美元符号, then < / em>“ stmt”。

您可以通过将负前瞻扩展到(?!\s*\$stmt)来修复该部分,但是第二个问题显而易见:将<query>匹配项扩展到下一个分号,不是后跟$stmt。您可以通过加紧<query>中的匹配来解决非分号而不是贪婪地匹配任何内容的问题。也就是说,(?<query>"select.*?\;)变为(?<query>"select[^;]*\;)。这会在第一个分号处造成比赛的死路。

如果您的SQL内有分号,则此匹配项将不匹配,但是。

能得到想要的结果吗?