regex — Как захватить только одну строку между разделителями из многострочных строк на основе определенной позиции

У меня есть небольшой веб-редактор 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

До сих пор у меня позиция каретки: row & столбец, и разрезать строку на две части: до каретки и после каретки.
Затем я получаю подстроку после появления последней точки с запятой в первой строке и подстроку перед появлением de first во второй строке.

Но я хочу знать, есть ли другие способы решить эту проблему с большей эффективностью.

0

Решение

Попробуйте регулярное выражение вроде этого:
/(?<=;)(.*)(?=\|)/

0

Другие решения

Для этого вы можете использовать подход регулярного или не регулярного выражения. Если ваши запросы будут содержать | (трубы) в них, тогда было бы более целесообразно назначить другой / уникальный маркер.

Код: (демонстрация)

$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 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
0

По вопросам рекламы [email protected]