Bashシェルスクリプトで連想配列をJSONに変換し出力する方法

2020-09-26Bash,JavaScript

はじめに

Bashでは、 declare コマンドを利用して連想配列変数を宣言することが可能です。

シェル内で定義した連想配列をJSONに変換し出力したいと思いましたが、どのように記述したらよいか悩んだためまとめました。

検証環境

$ uname -moi
x86_64 x86_64 GNU/Linux

$ bash -version | head -n 1
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)

事前準備

今回は、 jq コマンドを利用してJSON変換を実現してみたいと思います。

事前にインストールしておきましょう。

コードサンプル

事前に declare -A コマンドで宣言した連想配列に値を詰め込んでおき、 jq を使ってJSONオブジェクトに変換してみます。

# 返送配列変数を定義
$ declare -A MAP

# 連想配列に値をセット
$ MAP["key1"]=1
$ MAP["key2"]=2
$ MAP["key3"]="hoge"
$ MAP["key4"]=

# JSON変換
$ for i in "${!MAP[@]}"; do
  # 奇数行にキーを、偶数行に値を出力し、jqコマンドに食わせる
  echo "$i"
  echo "${MAP[$i]}"
done | jq -c -n -R 'reduce inputs as $i ({}; . + { ($i): (input|(tonumber? // .)) })'

実行結果は以下のようになります。

{"key4":"","key3":"hoge","key2":2,"key1":1}

key1key2 の値は数値ですので、出力されたJSONの値はダブルクォートで囲まれていません。
key4 の値は空となっていますので、空文字として出力されています。

jq-c オプションは、JSONをワンライナーで出力させるオプションです。

ポイントは jq -n -R コマンドで、標準入力から受け取ったプレーンなテキスト情報のうち、奇数行の値( $i に格納される )をキー、偶数行の値( input に格納される )をバリューとして、reduceさせている点です。

{}reduce の初期状態を表しています。

csvやテキストファイルのようなものにも適用できる

ロジックを見ての通り、奇数行にJSONオブジェクトのキー、偶数行にその値を出力していました。
つまり、同じロジックは連想配列ではないデータフォーマットにも適用できるわけです。

ひとこと

あんまり使うことないかな?と思いつつ。
csv2json などのようなツールを使ったほうが、集合を操作できるしロジックは簡潔ですし。

2020-09-26Bash,JavaScript