スペースで区切られた2つの列を含むテキストファイルがあります。
Foo Param1
Foo Param2
Foo Param3
Foo Param4
Foo Param5
Bar Stuff1
Bar Stuff2
Bar Param3
Bar Stuff4
etc
最初の列はグループ名で、2番目の列はそのグループ内の一意の属性です(属性名は2つの異なるグループに表示できますが、これは正常です)。
このファイルから次のSQLファイルを作成できることを願っています。
CREATE TABLE "Foo" (
id SERIAL PRIMARY KEY,
Param1 text,
Param2 text,
Param3 text,
Param4 text,
Param5 text
);
CREATE TABLE "Bar" (
id SERIAL PRIMARY KEY,
Stuff1 text,
Stuff2 text,
Param3 text,
Stuff4 text
);
テーブル名はファイルの最初の列から取得され、2番目の列は作成するフィールドとして使用されます。
今まで試したことはこれスレッドは次のとおりです。
awk -F ' ' 'BEGIN{IFS=","}NR>1{arr[$1]++}END{for (a in arr) print "CREATE TABLE IF NOT EXISTS " a " (" ${arr[*]} " )"}' file.txt
しかし、これは明らかに動作しません。
bash / Ubuntu 22.04でこれを達成する簡単な方法はありますか?
背景用:以下を使用して画像メタデータを抽出しました。exiftool
一つ食べてあげたいPostgreSQL各データベースには1つのテーブルがあります。グループレベル0では、すべてのタグが属性として見つかります。
したがって、テキストファイルの最初の列はEXIF
、XMP
またはのようなグループ名に対応しICC_Profile
、EXIF
グループの場合、2番目の列にはなどArtist
の値があります。ColorSpace
FNumber
答え1
しないでください。これは非常に悪いデザインパターンです。ソースデータファイルに新しい「グループ値」ペアが含まれているか欠落している場合は、そのグループのテーブルを再作成しますか?グループはいくつありますか?これが小さな定数であることは確実ですか?テーブル名をどのようにパラメータ化する予定ですか?
すでに持っているデータに従うテーブルを作成するだけです。
create table data (
group text,
flag text,
comment text,
primary key(group, flag)
);
EAVデータベーススキーマを理解します。https://en.wikipedia.org/wiki/Entity%E2%80%93attribute%E2%80%93value_model
答え2
ここです。形式は正確に望む形式ではありませんが、PostgreSQLはこれに満足しなければならないと思います。
awk '
# continuation lines separated by comma
$1 == table { print "," }
# new table needs preamble
$1 != table {
# may need to finish previous definition
if(table > "") { print ");" }
# preamble
table=$1;
printf "create table \"%s\" (\n", table
print "id SERIAL PRIMARY KEY,"
}
# field
{ printf "%s text\n", $2 }
# close final table
END { print ");" }
' datafile
答え3
awkを使用してください。
$ cat tst.awk
$1 != prev {
printf "%sCREATE TABLE \"%s\" (\n id SERIAL PRIMARY KEY", end, $1
end = "\n);\n"
prev = $1
}
{ printf ",\n %s text", $2 }
END { printf "%s", end }
$ awk -f tst.awk file
CREATE TABLE "Foo" (
id SERIAL PRIMARY KEY,
Param1 text,
Param2 text,
Param3 text,
Param4 text,
Param5 text
);
CREATE TABLE "Bar" (
id SERIAL PRIMARY KEY,
Stuff1 text,
Stuff2 text,
Param3 text,
Stuff4 text
);