正则表达式不在括号内
给定一个字符串,匹配在第一次出现单词后出现的所有内容。这个词不能出现在一对括号内的任何地方,但也可以是其他词。例如:正则表达式不在括号内
SELECT
t1.col1,
(SELECT t2.col1 FROM table2 t2
WHERE t2.id IN(SELECT * FROM table5 WHERE id = t2.id)
) AS alias1,
t1.col2
----------
FROM
table1 t1,
(SELECT id FROM table3 t3 WHERE t3.id = t1.table3_id) t3,
table4 t4
我正在寻找一切虚线AFTER - 具体而言,一切字FROM
一号外观不随地一对括号
内如果赢了的正则表达式后出现”不,我会制作一个PHP语句来解析。我也很难过,那么!我想要做到这一点,我将不得不用字符和括号来标记字符串?
我认为,正则表达式可能不是最好的解决方案在这里,因为他们可以非常困难的(或不可能)时,嵌套的括号都参与其中。
我也认为遍历每个字符并不是最好的方法,因为它会导致大量不必要的循环。
我觉得这是最好的办法:
查找指定字符串的每次出现,并且一次出现之前数括号的数量。如果开局参数的数量等于结束参数的数量,那么你有正确的匹配。这样做会减少循环,你只是检查你真正想要检查的内容。
我做了一个功能findWord
采取这种方法。它适用于您的示例,其中$in
是您的SQL语句,而$search
是'FROM'
。
function findWord($in, $search) {
if(strpos($in, $search) === 0) return $in;
$before = '';
while(strpos($in, $search, 1)) {
$i = strpos($in, $search, 1);
$before .= substr($in, 0, $i);
$in = substr($in, $i);
$count = count_chars($before);
if($count[40] == $count[41])
return $in;
}
return false;
}
我会给这个方法一个测试。我喜欢针对特定$搜索的概念,但它似乎以牺牲透明度为代价。最终,由于平均SQL语句长度,性能应该不成问题。感谢您的意见。 – rmirabelle
@rmirabelle如果你喜欢这个概念,那么upvote怎么样? ;)无论如何,我会在今天晚些时候通过并添加一些评论,以更好地解释函数。 –
upvote赚了 - 测试和工作 - 性能约为我的脚本在中等大小SQL块上的两倍。虽然两者都可以忽略不计:.0001与.0002 – rmirabelle
我打算采用编程方法,除非有人有更好的答案。
/**
* Find the portion of the SQL statement occurring after
* the first occurrence of the word 'FROM' (which itself
* does not appear within parens)
*/
public static function sql_after_from($sql) {
$arr = str_split($sql);
$indent = 0;
$out = '';
$start = 0;
$len = count($arr);
for($x=0; $x < $len; $x++) {
$c = $arr[$x]; //current character
if($c == '(') $indent++;
if($c == ')') $indent--;
$out .= $arr[$x];
//do the last 4 letters spell FROM?
if(substr($out, $x-3, $x) == 'FROM') {
if($indent == 0) { //not anywhere within parens
$start = $x+2;
break; //go no further
}
}
}
//everything after the first occurrence of FROM
return substr($sql, $start);
}
不能用正则表达式来处理一般情况;那些无法计数,因此不能告诉你在一个开放括号之后它又被关闭了。尽管如此,我不知道sql是否支持正则表达式的扩展。 –
我会考虑制作一个PHP函数,在这方面也有难度! – rmirabelle
你可以这样做:从第一个字母开始扫描FROM的字符串。为嵌套深度保留一个计数器,初始化为0.每当一个支架打开时,增加它;当括号关闭时,减少它(减1)。每当计数器!= 0时,只需扫描字符,直到计数器为0而不检查FROM。一旦你有第一次出现FROM,从那里开始的子字符串。 –