
/usr/local/pgsql15_1/bin/psql test15 <<EOF
begin;
drop COLLATION IF EXISTS special;
drop COLLATION IF EXISTS numeric;
CREATE COLLATION special (provider = icu, locale = 'en@colCaseFirst=upper;colReorder=grek-latn');
CREATE COLLATION numeric (provider = icu, locale = 'en@colNumeric=yes');
drop COLLATION IF EXISTS special;
drop COLLATION IF EXISTS numeric;
commit;
EOF
最初の部分は動的で、2番目のEOF部分は静的です。ループする方法を見つけようとしています。これまで私が試したことは次のとおりです。
VAR=$(cat<<EOF
begin;
drop COLLATION IF EXISTS special;
drop COLLATION IF EXISTS numeric;
CREATE COLLATION special (provider = icu, locale = 'en@colCaseFirst=upper;colReorder=grek-latn');
CREATE COLLATION numeric (provider = icu, locale = 'en@colNumeric=yes');
drop COLLATION IF EXISTS special;
drop COLLATION IF EXISTS numeric;
commit;
EOF
)
echo "$VAR"
arr_variable=("/usr/local/pgsql15_1/bin/psql test15" "/usr/local/pgsql14_5/bin/psql test14" "/usr/local/pgsql14_3/bin/psql test14")
for i in "${arr_variable[@]}"
do
echo "$i" "$VAR"
done
少し近いです。予想される動作:接続文字列を実行/評価します。 (最初のコードブロックに似ています)端末で。可能であれば、エラーが発生するとプロセスは終了し、エラーが印刷されます。
答え1
これにより、コマンド文字列を適切に分割するためにシェルに依存する必要がなくなります。データベース名と実行可能ファイルパス名の一意の部分をpsql
2つの別々の配列に保存することでこれを行います。
#!/bin/bash
statements=$(cat <<'END_SQL'
begin;
drop COLLATION IF EXISTS special;
drop COLLATION IF EXISTS numeric;
CREATE COLLATION special (provider = icu, locale = 'en@colCaseFirst=upper;colReorder=grek-latn');
CREATE COLLATION numeric (provider = icu, locale = 'en@colNumeric=yes');
drop COLLATION IF EXISTS special;
drop COLLATION IF EXISTS numeric;
commit;
END_SQL
)
psql_vers=( pgsql15_1 pgsql14_5 pgsql14_3 )
databases=( test15 test14 test14 )
set -- "${databases[@]}"
for psql_ver in "${psql_vers[@]}"; do
if ! printf '%s\n' "$statements" | "/usr/local/$psql_ver/bin/psql" "$1"
then
break
fi
shift
done
これにより、2つの配列が作成されます。 1つはpsql
バージョンディレクトリ用、もう1つはデータベース名用です。
これにより、データベース名が場所パラメータリストに送信され、shift
リストの後半にある最初のパラメータが重要になります。
ループはバージョンを繰り返し、psql
各バージョンの最初のデータベース名を引数として使用してその実行可能ファイルを呼び出して、標準入力ストリームにSQL文を送信します。次に、shift
場所パラメータリストからデータベース名を削除し、次の$1
反復に使用できる次のデータベース名を残します。
ループ内パイプの終了状態は、ループを早期に終了するかどうかを決定するために使用されますbreak
。エラーメッセージなどのすべての出力は、スクリプトの標準出力とエラーストリームに送信されます。