web-dev-qa-db-ja.com

jqを使用して複数の出力変数を割り当てる

jqを使用して TVDB api からの情報を解析しようとしています。いくつかのフィールドをプルして、bashスクリプトで引き続き使用できる変数に値を割り当てる必要があります。 variable="$(command)"を使用してbashを使用して出力を1つの変数に簡単に割り当てることができることはわかっていますが、複数の変数を生成するために出力が必要であり、複数のコマンドを使用させたくありません。

私はこのドキュメントを読みました:

https://stedolan.github.io/jq/manual/v1.5/#Advancedfeatures

しかし、これが私がやろうとしていることに関連しているかどうかはわかりません。

jq '.data'は次の出力を生成します。

[
  {
    "absoluteNumber": 51,
    "airedEpisodeNumber": 6,
    "airedSeason": 4,
    "airedSeasonID": 680431,
    "dvdEpisodeNumber": 6,
    "dvdSeason": 4,
    "episodeName": "We Will Rise",
    "firstAired": "2017-03-15",
    "id": 5939660,
    "language": {
      "episodeName": "en",
      "overview": "en"
    },
    "lastUpdated": 1490769062,
    "overview": "Clarke and Roan must work together in hostile territory in order to deliver an invaluable asset to Abby and her team."
  }
]

私は試した jq '.data | {episodeName:$name}'およびjq '.data | .episodeName as $name'1つを機能させるためだけに。私はドキュメントを理解していません、あるいはそれが私が探しているものであるとしても。私がやろうとしていることをする方法はありますか?

10
user2328273

readで個別の変数を使用できます:

read var1 var2 var3 < <(echo $(curl -s 'https://api.github.com/repos/torvalds/linux' | 
     jq -r '.id, .name, .full_name'))

echo "id        : $var1"
echo "name      : $var2"
echo "full_name : $var3"

配列の使用:

read -a arr < <(echo $(curl -s 'https://api.github.com/repos/torvalds/linux' | 
     jq -r '.id, .name, .full_name'))

echo "id        : ${arr[0]}"
echo "name      : ${arr[1]}"
echo "full_name : ${arr[2]}"

また、 jq 出力をいくつかの文字で分割することもできます:

IFS='|' read var1 var2 var3 var4 < <(curl '......' | jq -r '.data | 
    map([.absoluteNumber, .airedEpisodeNumber, .episodeName, .overview] | 
    join("|")) | join("\n")')

または、次のような配列を使用します。

set -f; IFS='|' data=($(curl '......' | jq -r '.data | 
    map([.absoluteNumber, .airedEpisodeNumber, .episodeName, .overview] | 
    join("|")) | join("\n")')); set +f

absoluteNumberairedEpisodeNumberepisodeName、およびoverviewは、それぞれ${data[0]}${data[1]}${data[2]}${data[3]}です。 set -fset +fは、それぞれ無効化と有効化に使用されます globbing

jq 部分の場合、すべての必須フィールドがマップされ、join("|")を含む'|'文字で区切られます。

Jq <1.5を使用している場合は、数値フィールドごとにtostringを使用して数値を文字列に変換する必要があります。例:

IFS='|' read var1 var2 var3 var4 < <(curl '......' | jq -r '.data | 
    map([.absoluteNumber|tostring, .airedEpisodeNumber|tostring, .episodeName, .overview] | 
    join("|")) | join("\n")')
8
Bertrand Martel

jqは、常に0個以上の値のストリームを生成します。たとえば、「episodeName」と「id」に対応する2つの値を生成するには、次のように記述します。

.data[] | ( .episodeName, .id )

目的に応じて、-cコマンドラインオプションを使用して、各JSON出力値が1行に表示されるようにすることが役立つ場合があります。また、JSON文字列である各出力値から最も外側の引用符を削除する-rコマンドラインオプションを使用することもできます。

その他のバリエーションについては、jq FAQ https://github.com/stedolan/jq/wiki/FAQ を参照してください。例:質問:

Q:jqによって生成されたJSONテキストのストリームを対応する値のbash配列に変換するにはどうすればよいですか?

6
peak