Чтение SQL файла по блокам в bash

Я пытался выполнить операцию замены строки в bash. Это не совсем так просто, как кажется, поэтому вот объяснение:

Допустим, у вас есть SQL-файл с несколькими операторами SELECT. Каждый блок SELECT заканчивается точкой с запятой (;).

Моя цель - взять каждый блок отдельно и выполнить с ним некоторую операцию. Однако скрипт должен уметь распознавать эти блоки динамически, поскольку он будет работать с разными sql файлами, и сохранять каждый блок в переменную (например, $1), чтобы блок можно было легко использовать позже.

PS Я бился над этой проблемой в течение последней недели, и любой совет будет очень признателен. Кроме того, ниже вы можете увидеть некоторые из regex-типов, которые я использовал до сих пор:

egrep -e "^(\s|SELECT).*.[^;]\s*" test.sql

и это

cat test.sql | awk '" "{found=0} /SELECT/{found=1} {if (found) print }'

Первый вариант работает лучше всего и ближе всего к цели, но я не могу найти способ разделить и сохранить блоки операторов SELECT. Второй вариант использует аналогичное выражение для поиска точки с запятой. В дополнение к этому я попытался указать сценарию использовать все, что находится между ними, в качестве третьего элемента, а затем попытаться сохранить эти три элемента вместе как единое целое. Однако это не сработало. Операторы SELECT являются многострочными.

0
07.03.2016, 17:24
2 ответа

Вы можете использовать цикл чтения с разделителем, отличным от символа новой строки. Это заставит команду read в bash рассматривать несколько строк как одну, при условии, что они заканчиваются вашим разделителем.

Примечание: этот метод не подходит, если точка с запятой может стоять в файле внутри комментариев или строк. Это не парсер, а простой цикл чтения.

while read -rd ';' sql
do
    if [ "${sql#SELECT}" = "$sql" ]
    then
        echo "Not a SELECT!"
    else
        echo "This is the command I got:"
        echo ">>$sql<<"
    fi
done < test.txt 

читается как -rd ';' sql будет читать ввод, пока не увидит точку с запятой. Блок будет в переменной $ sql .

if внутри цикла проверяет, изменяет ли удаление слова SELECT из начала текста в переменной его - в основном он спрашивает, не начинается ли текст со слова ВЫБРАТЬ .

Обратите внимание, что read удалит начальные и конечные пробелы в каждом блоке при поиске «слов». Поэтому пустые строки до и после точки с запятой удаляются.

Пример текстового файла:

   SELECT *
FROM PLANTS

WHERE TYPE='BUSH'

;

INSERT INTO PLANTS (TYPE,NAME,ID)
VALUES ('TREE', 'Oak', 15)    ;   

SELECT NAME
FROM PLANTS
WHERE NAME LIKE 'O%';

Результатом будет следующий вывод:

This is the command I got:
>>SELECT *
FROM PLANTS

WHERE TYPE='BUSH'<<
Not a SELECT!
This is the command I got:
>>SELECT NAME
FROM PLANTS
WHERE NAME LIKE 'O%'<<
0
28.01.2020, 04:52
awk -v RS=";" '/SELECT/{print $0";"}'

Если запись (где RS - ;) имеет строку SELECT, то она будет напечатана вместе с ; в конце.

0
28.01.2020, 04:52

Теги

Похожие вопросы