jq出力をBash変数に設定する

jq出力をBash変数に設定する

次のように、REST APIからJSONを返すためにカールを使用しています。

content=$(curl -s  -X GET -H "Header:Value" http://127.0.0.1:8200/etc)
echo "${content}"| jq -r '.data.value'

それは私に必要な価値を生み出します。ただし、上記のコードを次のように変更すると:

content=$(curl -s  -X GET -H "Header:Value" http://127.0.0.1:8200/etc)
username=$(echo "${content}"| jq -r '.data.value')
echo $username

何も生産されません。出力がユーザー名変数に割り当てられるように、これをどのように変更できますか?

答え1

コードを次のように変更しましたが、うまくいきました。

content=$(curl -s  -X GET -H "Header:Value" http://127.0.0.1:8200/etc) 
username=$( jq -r  '.data.value' <<< "${content}" ) 
echo "${username}"

答え2

次のように1行に変換できます。

username=$( curl -s  -X GET -H "Header:Value" http://127.0.0.1:8200/etc |  jq -r  '.data.value' ) 
echo ${username}

答え3

これは、2行目の「エコー」が失われた場合にのみ機能します。

content=$(curl -s  -X GET -H "Header:Value" http://127.0.0.1:8200/etc) 
username=$( echo jq -r  '.data.value' <<< "${content}" ) 
echo ${username}

答え4

readjqの出力をFIFOに接続するプロセス置換と組み込みのbashを使用できます。

read username < <(curl -s -X GET -H "Header:Value" http://127.0.0.1:8200/etc | jq -r '.data.value')

他の提案された解決策は、jq値を割り当てるだけでより簡単です。read現在のソリューションは、複数のキーを複数のシェル変数に一度に割り当てる必要がある場合に便利ですread var1 var2 var3 < <(...)

以下は、jq出力をシェル変数に割り当てるより一般的なコードの断片です。これは非常に便利です。

シングルライン入力のための2つの方法(ループなし):

IFS=$'\n' read -rd '' a b < <(echo '{"a":"1","b":"2"}' | jq -r '(.a, .b)'); declare -p a b
  declare -- a="1"
  declare -- b="2"

read a b < <(echo '{"a":"1","b":"2"}' | jq -r '[.[]] | @tsv'); declare -p a b
  declare -- a="1"
  declare -- b="2"

注1:@tsvはスペース区切り文字を使用します。スペースを含めることができる値には@csv形式を使用できます。注2:IFS=$'\n' read -rd '' a b <空の出力行がないとします。一部のjsonキーが空の場合は、 '--raw'なしで 'jq'を使用してから"'s'を削除するか、代わりにa=${a:1:-1}'s'を使用できます(以下の例を参照)。readarrayread

複数行入力のための3つの方法(ループを含む):

echo '[{"a":"1","b":"2"},{"a":"3","b":"4"}]' |
  jq -r '.[] | {a, b} | [.[]] | @csv' |
  while IFS= read -r i; do
    IFS=, read -r a b <<< "$i"; a=${a:1:-1}; b=${b:1:-1}; declare -p a b;
  done

  declare -- a="1"
  declare -- b="2"
  declare -- a="3"
  declare -- b="4"

echo '[{"a":"1","b":"2"},{"a":"3","b":"4"}]' |
  jq -r '.[] | (.a, .b)' |
  while IFS= read -r a; do
    IFS= read -r b; declare -p a b;
  done

  declare -- a="1"
  declare -- b="2"
  declare -- a="3"
  declare -- b="4"

echo '[{"a":"1","b":"2"},{"a":"3","b":"4"}]' |
  jq -r '.[] | (.a, .b)' |
  while readarray -n2 lines && [ ${#lines} -ne 0 ]; do
    a="${lines[0]:0:-1}"; b="${lines[1]:0:-1}"; declare -p a b;
  done

  declare -- a="1"
  declare -- b="2"
  declare -- a="3"
  declare -- b="4"

関連情報