PHP - 如何根据定义的位置从多行字符串中捕获分隔符之间的一个字符串

问题描述 投票:0回答:2

我有一个小的Web sql编辑器,但当用户写一个查询,如:

SELECT * FROM users;
SELECT * FROM references;|  <-- here is the caret, i want to run only this query
SELECT * FROM settings

并提交该字符串,只执行第一个查询。我想只运行用户插入符所在的查询。

显然,该示例看起来很简单,但考虑在真实环境中使用的更真实的查询,例如:

SELECT col1,col2,col3
FROM users
WHERE id IN (1,2,3,4);
SELECT * FROM references WHERE status = 1
;
SELECT 
    a.col1
    , a.col2
    , b.col1 
FROM table_a a |                            <--- Here is the caret, run this query
    INNER JOIN table_b b ON b.id_table_a = a.id
WHERE a.id = 5
;
UPDATE table_a SET col1 = 'demo' WHERE id = 3;
-- etc, etc, etc

到目前为止,我有插入位置:行和列,并将字符串分为两部分:插入符号之前和插入符号之后。然后我在第一个字符串的最后一个分号出现后得到子字符串,并在第一个出现在第二个字符串之前得到子字符串。

但我想知道是否有其他方法可以更有效地解决这个问题。

php regex delimiter multiline
2个回答
0
投票

尝试这样的正则表达式语句:/(?<=;)(.*)(?=\|)/


0
投票

您可以使用正则表达式或非正则表达式方法。如果您的查询将包含|(管道),那么更适合提名不同/唯一标记。

代码:(Demo

$queries="
SELECT col1,col2,col3
FROM users
WHERE id IN (1,2,3,4);
SELECT * FROM references WHERE status = 1
;
SELECT 
    a.col1
    , a.col2
    , b.col1 
FROM table_a a |                            <--- Here is the caret, run this query
    INNER JOIN table_b b ON b.id_table_a = a.id
WHERE a.id = 5
;
UPDATE table_a SET col1 = 'demo' WHERE id = 3;
-- etc, etc, etc";

$rtrimmed=substr($queries,0,strpos($queries,'|'));     // remove substr following pipe
$ltrimmed=substr($rtrimmed,strrpos($rtrimmed,';')+1);  // remove substr upto latest semicolon
echo trim($ltrimmed);                                  // remove whitespace on either side

echo "\n---\n";

echo preg_match('~;\s*\K[^;|]*?(?= *\|)~',$queries,$out) ? $out[0] : '';

输出:

SELECT 
    a.col1
    , a.col2
    , b.col1 
FROM table_a a
---
SELECT 
    a.col1
    , a.col2
    , b.col1 
FROM table_a a

Pattern Demo

模式细分:

~         #pattern delimiter
;\s*      #match semicolon followed by zero or more whitespace characters
\K        #restart the fullstring match (release previous matched characters)
[^;|]*?   #match zero or more (lazily) non-semicolon and non-pipe characters
(?= *\|)  #look ahead for zero or more spaces followed by a pipe (so that the output is trimmed)
~         #pattern delimiter
© www.soinside.com 2019 - 2024. All rights reserved.