使用jq分配多个输出变量

use*_*273 7 bash television jq

我试图用来jq解析来自TVDB api的信息。我需要提取几个字段,并将值分配给可以在bash脚本中继续使用的变量。我知道我可以通过bash轻松地将输出分配给一个变量,variable="$(command)"但是我需要输出来产生多个变量,并且我不想使用多个命令。

我阅读了此文档:

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."
  }
]
Run Code Online (Sandbox Code Playgroud)

我尝试过jq '.data | {episodeName:$name}'jq '.data | .episodeName as $name'只是想让一个工作。我不理解文档,即使我正在寻找它。有办法做我想做的事吗?

Ber*_*tel 34

您可以使用单独的变量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"
Run Code Online (Sandbox Code Playgroud)

使用数组:

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]}"
Run Code Online (Sandbox Code Playgroud)

你也可以用一些字符分割输出:

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

或者使用像这样的数组:

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

absoluteNumber, airedEpisodeNumber, episodeName&overview分别是${data[0]}, ${data[1]}, ${data[2]}, ${data[3]}set -fset +f分别用于禁用和启用globbing

对于部分,所有必填字段都被映射并用一个'|'字符分隔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")')
Run Code Online (Sandbox Code Playgroud)

  • 另外,`&lt; &lt;(curl...` 和之前的`&lt;&lt;&lt; $(curl ...`) 之间有什么区别? (2认同)
  • 我已经用 jq &lt; 1.5 的字符串转换更新了我的帖子。`&lt; &lt;(...)` 是进程替换,对于 `&lt;&lt;&lt;` 右边的字符串被扩展。请参阅[这篇文章](http://askubuntu.com/a/678919/463299)以获得完整的解释 (2认同)

pea*_*eak 6

jq总是产生零个或多个值的流。例如,要生成对应于“ episodeName”和“ id”的两个值,您可以编写:

.data[] | ( .episodeName, .id )
Run Code Online (Sandbox Code Playgroud)

为了您的目的,使用-c命令行选项可能会有所帮助,以确保每个JSON输出值都显示在一行上。您可能还需要使用-r命令行选项,该选项从每个JSON字符串的输出值中删除最外面的引号。

有关进一步的变化,请参见jq FAQ https://github.com/stedolan/jq/wiki/FAQ,例如问题:

问:如何将jq生成的JSON文本流转换为对应值的bash数组?

  • 这向我展示了如何仅过滤掉我已经可以做的两个值,但是如何在脚本中进一步使用这些值作为变量呢? (3认同)