我希望在参数化的SQL查询中匹配占位符(裸?
,不带引号),如下所示:
UPDATE `table` SET `col1`=? WHERE `col2`=? AND `x`="??as"
(我知道我应该使用SQL::Parser
代替。请在这里与我联系。)
此正则表达式(?:`.+?`)|(?:'.+?')|(?:".+?")|(\?)
与`col1`=?
和`col2`=?
中的裸问号相匹配,但跳过`x`="??as"
中双引号内的问号,正如我所希望的那样。您可以在https://regex101.com/r/iH4aV2/3处看到此工作。
现在,正则表达式由PCRE运行。如果我运行这个Perl:
# same regex and test string
my $x = 'UPDATE `table` SET `col1`=? WHERE `col2`=? AND `x`="??as"';
while ($x =~ /(?:`.+?`)|(?:'.+?')|(?:".+?")|(\?)/g) {
print "A:".pos($x)."\n";
}
我明白了:
A:14
A:25
A:27
A:40
A:42
A:50
A:57
我期待只获得遗留问号的位置,就像在regex101网站上一样:
A:27
A:42
为什么会这样?我可以让Perl的正则表达式引擎像PCRE一样吗?
答案 0 :(得分:3)
最简单的解决方案是在检查pos
之前检查捕获的parens是否实际捕获了某些东西:
my $x = 'UPDATE `table` SET `col1`=? WHERE `col2`=? AND "x"="??as"';
while($x =~ /(?:`.+?`)|(?:'.+')|(?:".+?")|(\?)/g) {
if (defined($1)) {
print "A:".pos($x)."\n";
}
}
这会产生预期的结果。
(我的意思是,你可以使用评论中提到的花哨的(*SKIP)
和(*FAIL)
动词,但这看起来更清晰了)