私はBashで文字列置換型の操作を実行しようとしてきました。しかし、見るほど簡単ではありません。これの説明は次のとおりです。
複数のSQLファイルが含まれているとします。選ぶそこにある声明。各選ぶブロックはセミコロン(;)。
私の目標は、各チャンクを個別に保持し、いくつかのタスクを実行することです。ただし、スクリプトは異なるSQLファイルを使用して各ブロックを変数に格納するため、これらのブロックを動的に識別できる必要があります(例:1)後でブロックを簡単に使用できるようにします。
PS私は先週この問題で苦労しました。アドバイスをいただきありがとうございます。また、以下では、これまでに使用したいくつかの正規表現型項目を表示できます。
egrep -e "^(\s|SELECT).*.[^;]\s*" test.sql
この
cat test.sql | awk '" "{found=0} /SELECT/{found=1} {if (found) print }'
最初の方法が最もうまく機能し、目標に最も近いですが、SELECTステートメントブロックを分離して保存する方法が見つかりませんでした。 2番目は、同様の表現を使用してセミコロンを探します。それ以外は、2つの項目の間にあるすべての項目を3番目の項目として使用するようにスクリプトに指示し、3つの項目をまとめて保存してみました。しかし、正しく動作しませんでした。 SELECT 文は複数行です。
答え1
「newline」以外の区切り文字を使用して読み取りループを使用できます。これにより、read
コマンドはbash
区切り文字で終わると複数行を1つとして扱います。
注:この方法は、ファイルのコメントまたは文字列にセミコロンが表示される場合は適していません。これはパーサーではありません。単なる読み込みループです。
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
read -rd ';' sql
セミコロンが表示されるまで入力を読みます。ブロックは変数に配置されます$sql
。
if
ループ内で変数のテキストの先頭から単語を削除すると、変更されることをSELECT
確認します。基本的には、テキストが単語で始まらないかどうかを尋ねることです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%'<<
答え2
awk -v RS=";" '/SELECT/{print $0";"}'
レコード(is RS
);
に文字列がある場合は、SELECT
最後に一緒に印刷されます。;