多くのレコードを含むLinuxシステムにテーブルがあります。以下を取得するためにクエリを実行しています。
select * from TABNAME_XYZ
CID CN XY NAT UIC DATE Region
12 2123 120.9 29.0 100.0 2018-06-08 JAIPUR
13 0987 78.9 100.3 28.8 2020-12-09 DELHI
出力をJSONに変換するシェルスクリプトを作成したいのですが、どこから始めるべきか、何をすべきかわかりません。 JSONは次のようになります。
{"CID":"12","CN":"2123","DATA":{"XY":120.9,"NAT":29.0,"UIC":100.0,"Date":"2018-06-08","REGION":"JAIPUR"}},
{"CID":"13","CN":"0987","DATA":{"XY":78.9,"NAT":100.3,"UIC":28.8,"Date":"2020-12-09","REGION":"DELHI"}}
jq
すでに私のシステムにいます。
答え1
フィールドが常に指定された順序であり、入力の最初の行にヘッダー行があり、複数のスペース文字がフィールドを区切ると仮定すると、圧縮された連続スペースを使用してを使用してデータtr
を解析できますjq
。
database-client-command |
tr -s ' ' |
jq -c -Rn '
input | split(" ") as $head |
inputs | split(" ") |
to_entries |
map(.key = $head[.key]) |
[ .[:2][], { key: "DATA", value: (.[2:] | from_entries) } ] |
from_entries'
この式は別の行からjq
生データを読み込みます。tr
最初の行はヘッダーに分割され、配列に格納されます$head
。
ヘッダーで行ったように、残りの行を配列に分割します。フィルタは各配列を「入力型」(キー付きto_entries
オブジェクトの集合)に変換し、数値配列インデックスをキーインヘッダーに置き換えます。key
value
map()
$head
その後、map()
フィルタは配列を並べ替えて、3番目の要素を別の子オブジェクトにDATA
移動し、「アイテムフォーム」から再変換します。
キーとデータが再配置されると、from_entries
フィルタは「入力フォーム」から配列を返します。
スクリプトの出力は一連のJSONオブジェクトになり、質問にデータが与えられると、これらのオブジェクトは次のようになります。
{"CID":"12","CN":"2123","DATA":{"XY":"120.9","NAT":"29.0","UIC":"100.0","DATE":"2018-06-08","Region":"JAIPUR"}}
{"CID":"13","CN":"0987","DATA":{"XY":"78.9","NAT":"100.3","UIC":"28.8","DATE":"2020-12-09","Region":"DELHI"}}
Region
にREGION
変更するには、データベースの照会中または後処理ステップでこれを実行することをお勧めしますDATE
。Date
最初の行の末尾のコンマのため、期待される結果は有効なJSONではありません。
答え2
実際にDATE
と に変換したくない(もしそうする場合、変更するタグを選択するロジックを説明すれば簡単な調整である)、最後に(もう一度言うが、そうしないと簡単な調整です)そして、すべてのUnixシステムのすべてのシェルでawkを使用してください。Date
Region
REGION
,
$ cat tst.awk
NR==1 {
split($0,tags)
next
}
{
printf "%s{%s,%s,\"DATA\":{", sep, fmt(1), fmt(2)
for (i=3; i<=NF; i++) {
printf "%s%s", fmt(i), (i<NF ? "," : "}}")
}
sep = ",\n"
}
END {
print ""
}
function fmt(fldNr, tag, val) {
tag = tags[fldNr]
val = $fldNr
gsub(/"/,"\\\"",val)
return sprintf("\"%s\":\"%s\"", tag, val)
}
$ awk -f tst.awk file
{"CID":"12","CN":"2123","DATA":{"XY":"120.9","NAT":"29.0","UIC":"100.0","DATE":"2018-06-08","Region":"JAIPUR"}},
{"CID":"13","CN":"0987","DATA":{"XY":"78.9","NAT":"100.3","UIC":"28.8","DATE":"2020-12-09","Region":"DELHI"}}
答え3
これは一つの方法です。以下を次のように保存しますfoo.awk
。
{
if(NR==1){
for(i=1;i<=NF;i++){
head[i]=$i
}
}
else{
printf "{\"%s\":\"%s\",\"%s\":\"%s\",\"DATA\":{\"%s\":%s,\"%s\":%s,\"%s\":%s,\"%s\":\"%s\",\"%s\":\"%s\"}}\n", head[1],$1,head[2],$2,head[3],$3,head[4],$4,head[5],$5,head[6],$6,head[7],$7;
}
}
それから:
$ cat file | awk -f foo.awk
{"CID":"12","CN":"2123","DATA":{"XY":120.9,"NAT":29.0,"UIC":100.0,"DATE":"2018-06-08","Region":"JAIPUR"}}
{"CID":"13","CN":"0987","DATA":{"XY":78.9,"NAT":100.3,"UIC":28.8,"DATE":"2020-12-09","Region":"DELHI"}}
ここでは、コマンドの出力をselect
ファイルに保存しましたfile
。あなたの場合は、データベース内のコマンドラインクライアントを使用できます。たとえば、mySQLを使用すると、次のようになります。
mysql -e 'select * from TABNAME_XYZ' | awk -f foo.awk