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

Regex 为什么这种消极的前瞻不起作用?,regex,pcre,Regex,Pcre,我有一个正则表达式,可以帮助我查找和替换不推荐的mysql查询。然而,出于某种原因,一旦我替换了一个查询,它将重新捕获相同的区域,并仅将其扩展到下一个不推荐使用的查询的末尾。我试图通过不让它选择替换字符串(stmt)中的特定关键字来解决这个问题,但是由于某种原因它忽略了这个约束 \(?mis)\$(?[a-z0-9]*)=(?“选择”。)(?:(?!stmt)。*?)\$(?[a-z0-9]*?)=mysql\U查询。*?\;(?*),而\s(\$(?[a-z0-9]*?)=mysql.*{1

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

\(?mis)\$(?[a-z0-9]*)=(?“选择”。)(?:(?!stmt)。*?)\$(?[a-z0-9]*?)=mysql\U查询。*?\;(?*),而\s(\$(?[a-z0-9]*?)=mysql.*{
1

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

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



1.我正在使用
(?mis)
,因为PHPStorm不能很好地处理普通标志。
2.防止随机代码和不良格式妨碍图案

3.如果这是一个XY问题,我应该以另一种方式强制正确匹配,我欢迎将其作为一个答案。

反向前瞻不匹配是因为它不匹配。当
末尾的分号紧跟在“stmt”之后时,它会拒绝匹配,这在代码中不是这样的:后面跟着换行符、空格、美元符号,然后是“stmt”

您可以通过将负前瞻扩展到
(?!\s*\$stmt)来修复该部分
,但第二个问题变得很明显:这只是将
匹配扩展到下一个分号,后面没有
$stmt
。您可以通过收紧
中的匹配来解决这一问题,以便在非分号上进行贪婪的匹配,而不是在任何分号上进行贪婪的匹配。也就是说,
(?“选择。*?\)
将成为
(?)选择[^;]*\;)
。这将在第一个分号处创建匹配的死止点

如果您的SQL中有分号,这将无法匹配,但是,嘿


这是否得到了期望的结果?

您一定是指
(?:(?!stmt)。*?
@WiktorStribiżew-如果我使用它,它会将$query(红色)匹配项拉到“$result”行末尾的
,即使您将其切碎为
(?mis)\$(?[a-z0-9]*)[]=[](?“select.*)(?:(?:(!stmt)。)*\$
,在一个全局上下文中,点东西只会吹过一行行垃圾。您必须明确说明您要匹配的内容,因为它在您的正则表达式中并不明显。如果您正在查找包含
mysql\u query
的弃用代码,则无需再查找任何其他内容:
mysql\u query
不再是从PHP7.0开始支持。@sln-我不明白你的意思。谢谢!使用此模式以及条件lookhead来检查查询中的分号-
(?(?=\;\”)\“\”\”\“;\124;\)
-似乎工作得很好。