Php 正则表达式问题

Php 正则表达式问题,php,regex,Php,Regex,我有一个这样的问题 SELECT a, (SELECT b FROM w), (SELECT c FROM x) FROM y WHERE a IN (SELECT d FROM z) 我想把它转换成 SELECT COUNT(*) FROM y WHERE a IN (SELECT d FROM z) 在php中。这是一个样品,要求与此不同 实际上,正则表达式必须只使用COUNT*替换first SELECT和FROM pair之间的所有内容,但之后不要触摸SELECT。并且还必须考虑在第

我有一个这样的问题

SELECT a, (SELECT b FROM w), (SELECT c FROM x) FROM y WHERE a IN (SELECT d FROM z)
我想把它转换成

SELECT COUNT(*) FROM y WHERE a IN (SELECT d FROM z)
在php中。这是一个样品,要求与此不同

实际上,正则表达式必须只使用COUNT*替换first SELECT和FROM pair之间的所有内容,但之后不要触摸SELECT。并且还必须考虑在第一对中有其他对的选择,并替换它们。

我现在用这个

preg_replace('/SELECT (.*?) FROM/', 'SELECT COUNT(*) AS count FROM', $sql, 1)
但是它没有检测到第一个SELECT*FROM

preg_replace中的SELECT,这看起来有些过分了。为什么不使用str_replace或更好的str_ireplace

如果查询不总是相同的,您可以:


$sql = 'SELECT f1, f2, (SELECT f3 FROM t2) FROM t1 WHERE f1 IN (SELECT f4 FROM t)';
$fixed_sql = 'SELECT COUNT(*) ' . substr($sql, strpos($sql, ' FROM');
未经测试,但概念相同。

如何:

$sql = preg_replace("/^.*( FROM t1)/", "SELECT COUNT(*)$1", $sql);

假设您使用regex将SELECT和FROM之间的所有内容替换为COUNT*。使用简单的正则表达式模式,可以通过两种不同的方式实现:

贪婪地匹配SELECT和FROM之间的所有内容 懒洋洋地在SELECT和FROM之间匹配所有内容 让我们以您的输入为例:

SELECT f1, f2, (SELECT f3 FROM t2) FROM t1 WHERE f1 IN (SELECT f4 FROM t)
备选方案1将与以下内容相匹配:

SELECT f1, f2, (SELECT f3 FROM t2) FROM t1 WHERE f1 IN (SELECT f4 FROM
SELECT f1, f2, (SELECT f3 FROM
第一个选择,最后一个选择

选项2应符合以下要求:

SELECT f1, f2, (SELECT f3 FROM t2) FROM t1 WHERE f1 IN (SELECT f4 FROM
SELECT f1, f2, (SELECT f3 FROM
第一个选择和第一个从

用其他模式替换任一模式都会破坏SQL。当然,有更聪明的方法来创建一个模式来解释这个特定的SQL输入,但我非常确信,对于每个智能正则表达式,我或其他人都会很容易找到一个SQL脚本,它会被它破坏

您可能会认为使用递归模式,但它们的编写和维护非常困难,而且它们也会破坏SQL代码,如下所示:

SELECT ... WHERE x='FOO WHERE BAR' ...
包含关键字的文本字符串

包含关键字的注释


所以,我的答案是:不要使用正则表达式。使用某种形式的替换。

对于您给出的特定图案:

选择。。。从

以下工作:

$sql = preg_replace('/^SELECT .*\(.*\) (FROM.*)$/', 'SELECT COUNT(*) $1', $sql);

但正如@Bart所指出的,任何偏离这种模式的行为都会破坏SQL。

这听起来是一项非常奇怪的任务。你可能想想想你为什么要这么做,如果有更好的解决方案来解决更高层次的问题,那么实际的模式是什么?因为你可以这样做:str_replace'SELECT f1,f2,SELECT f3 FROM t2 FROM t1,f1 FROM t,SELECT f4 FROM t',SELECT COUNT*FROM t1,f1 FROM t,SELECT f4 FROM t',如果这只是你可以使用str_replace,我认为你不需要正则表达式。您可以用SELECT COUNT*替换之前的所有内容,使用substr\u replace.@Ali您正在编写分页器吗?指定该选项将产生更好的响应。查询并不总是这样:它是一个样本。然后,您想用COUNT*right?替换列列表,并将其编辑为lazyly,这似乎是一个更好/更常见的术语。如果您喜欢另一种方式,请随意后退。要不然,就来吧。@Justin,不,这样没关系。干杯,谢谢你的回答。我自己想出来的:{SELECT?:?:?!SELECT | FROM.+| SELECT?1FROM*FROM}six