我有这个正则表达式,可以帮助我查找和替换不推荐使用的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
1.我使用(?mis)
是因为PHPStorm在正常标志下不能很好地发挥作用。
2.防止随机代码和错误的格式妨碍模式
3.如果这是一个XY问题,并且我应该以其他方式强制正确匹配,那么我欢迎您回答。
答案 0 :(得分:1)
否定的前瞻不匹配是因为它不匹配。当<query>
末尾的分号后紧跟“ stmt”时,它会拒绝匹配,这在您的代码中不是这种情况:后跟换行符,空格,美元符号, then < / em>“ stmt”。
您可以通过将负前瞻扩展到(?!\s*\$stmt)
来修复该部分,但是第二个问题显而易见:将<query>
匹配项扩展到下一个分号,不是后跟$stmt
。您可以通过加紧<query>
中的匹配来解决非分号而不是贪婪地匹配任何内容的问题。也就是说,(?<query>"select.*?\;)
变为(?<query>"select[^;]*\;)
。这会在第一个分号处造成比赛的死路。
如果您的SQL内有分号,则此匹配项将不匹配,但是。
能得到想要的结果吗?