次のJSON配列があります。
{
"SITE_DATA": {
"URL": "example.com",
"AUTHOR": "John Doe",
"CREATED": "10/22/2017"
}
}
各項目のキーを変数名に設定し、値をその値に設定できるように、jqを使用してこの配列を繰り返したいと思います。
例:
- URL="example.com"
- 著者 = "ジョン・ドー"
- 作成済み="2017年10月22日"
これまでに得たのは、配列を繰り返しながら文字列を生成することです。
constants=$(cat ${1} | jq '.SITE_DATA' | jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]")
任意の出力:
URL=example.com
AUTHOR=John Doe
CREATED=10/22/2017
スクリプトで次の変数をさらに使用したいと思います。
echo ${URL}
ただし、これは現在の空の出力を反映しています。そこに何かが必要なようですが、eval
手に握ることができないようです。
ベストアンサー1
作成者名にスペースが含まれているため、元のバージョンは実行されません。環境変数がに設定されたコマンドをeval
実行すると解釈されます。実際に独自にパイプする必要もありません。Doe
AUTHOR
John
jq
内部パイプラインとデータフローさまざまなフィルタを一緒に接続できます。
これはすべて入力データを完全に信頼する場合にのみ意味があります(例えば、制御するツールによって生成されたデータ)。いくつかの考えられる問題を以下に詳細に説明するが、データ自体は確かに現在予想される形式であると仮定する。
jqプログラムのより簡単なバージョンを作成できます。
jq -r '.SITE_DATA | to_entries | .[] | .key + "=" + (.value | @sh)'
出力:
URL='example.com'
AUTHOR='John Doe'
CREATED='10/22/2017'
不要map
:.[]
パイプラインの残りの部分を通して、配列内の各オブジェクトを別々の項目として扱います。したがって、最後の項目以降のすべての内容は|
それぞれに個別に適用されます。最後に、+
適切な文字列を含む一般的な接続を使用して、有効なシェル割り当て文字列を単純に組み合わせます。値を引用してエスケープします。@sh
。
ここでは、すべてのパイプが重要です。パイプが存在しない場合は、プログラムのさまざまな部分が微妙に異なるコンテキストで評価される無駄なエラーメッセージが表示されます。
この文字列eval
は入力データを完全に信頼する場合希望の効果を得る。
eval "$(jq -r '.SITE_DATA | to_entries | .[] | .key + "=" + (.value | @sh)' < data.json)"
echo "$AUTHOR"
いつものようにeval
、データが悪意のあるまたは予期しない形式の場合、重大なエラーが発生する可能性があるため、信頼できるデータに注意してください。特に、鍵$
実行中のコマンドを生成するシェルメタ文字(または空白など)を含みます。たとえば、PATH
誤って環境変数を上書きすることがあります。
データが信頼できない場合は、この操作をまったく実行しないか、まず目的のキーのみを含むようにオブジェクトをフィルタリングしてください。
jq '.SITE_DATA | { AUTHOR, URL, CREATED } | ...'
次のような場合でも問題が発生する可能性があります。値配列なので.value | tostring | @sh
もっといいでしょう。ただし、この警告リストは良い理由になる可能性があります。いいえこれらすべてを最初に行います。
以下を生成することもできます。連想配列代わりに、キーと値の両方が引用されます。
eval "declare -A data=($(jq -r '.SITE_DATA | to_entries | .[] | @sh "[\(.key)]=\(.value)"' < test.json))"
その後、${data[CREATED]}
キーや値の内容が何であれ、作成日などが含まれます。これは最も安全なオプションですが、エクスポートできる最上位レベルの変数は生成されません。値が配列の場合、まだBash構文エラーが発生する可能性があります。オブジェクトの場合、まだjqエラーが発生する可能性がありますが、コードが実行されたり何も上書きされません。