bash 使用 jq 分配多个输出变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/43291389/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
using jq to assign multiple output variables
提问by user2328273
I am trying to use jq
to parse information from the TVDB api. I need to pull a couple of fields and assign the values to variables that I can continue to use in my bash
script. I know I can easily assign the output to one variable through bash with variable="$(command)"
but I need the output to produce multiple variables and I don't want to make to use multiple commands.
我正在尝试用于jq
解析来自TVDB api 的信息。我需要提取几个字段并将值分配给我可以继续在我的bash
脚本中使用的变量。我知道我可以通过 bash 轻松地将输出分配给一个变量,variable="$(command)"
但我需要输出来生成多个变量,而且我不想使用多个命令。
I read this documentation:
我阅读了这个文档:
https://stedolan.github.io/jq/manual/v1.5/#Advancedfeatures
https://stedolan.github.io/jq/manual/v1.5/#Advancedfeatures
but I don't know if this relevant to what I am trying to do.
但我不知道这是否与我正在尝试做的有关。
jq '.data'
produces the following output:
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."
}
]
I tried jq '.data | {episodeName:$name}'
and jq '.data | .episodeName as $name'
just to try and get one working. I don't understand the documentation or even if it's what I'm looking for. Is there a way to do what I am trying to do?
我试过jq '.data | {episodeName:$name}'
,jq '.data | .episodeName as $name'
只是想让一个工作。我不理解文档,即使它是我正在寻找的。有没有办法做我想做的事?
采纳答案by Bertrand Martel
You can use separate variables with read
:
您可以使用单独的变量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"
Using array :
使用数组:
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]}"
Also you can split jqoutput with some character :
你也可以用一些字符分割jq输出:
IFS='|' read var1 var2 var3 var4 < <(curl '......' | jq -r '.data |
map([.absoluteNumber, .airedEpisodeNumber, .episodeName, .overview] |
join("|")) | join("\n")')
Or use an array like :
或者使用像这样的数组:
set -f; IFS='|' data=($(curl '......' | jq -r '.data |
map([.absoluteNumber, .airedEpisodeNumber, .episodeName, .overview] |
join("|")) | join("\n")')); set +f
absoluteNumber
, airedEpisodeNumber
, episodeName
& overview
are respectively ${data[0]}
, ${data[1]}
, ${data[2]}
, ${data[3]}
. set -f
and set +f
are used to respectively disable & enable globbing.
absoluteNumber
, airedEpisodeNumber
, episodeName
&overview
分别是${data[0]}
, ${data[1]}
, ${data[2]}
, ${data[3]}
。set -f
和set +f
分别用于禁用和启用globbing。
For the jqpart, all your required fields are mapped and delimited with a '|'
character with join("|")
对于jq部分,所有必填字段都被映射并用一个'|'
字符分隔join("|")
If your are using jq < 1.5, you'll have to convert Number to String with tostring
for each Number fields eg:
如果您使用的是 jq < 1.5,则必须tostring
为每个数字字段将数字转换为字符串,例如:
IFS='|' read var1 var2 var3 var4 < <(curl '......' | jq -r '.data |
map([.absoluteNumber|tostring, .airedEpisodeNumber|tostring, .episodeName, .overview] |
join("|")) | join("\n")')
回答by peak
jq always produces a stream of zero or more values. For example, to produce the two values corresponding to "episodeName" and "id"' you could write:
jq 总是产生零个或多个值的流。例如,要生成对应于“episodeName”和“id”'的两个值,您可以编写:
.data[] | ( .episodeName, .id )
For your purposes, it might be helpful to use the -c command-line option, to ensure each JSON output value is presented on a single line. You might also want to use the -r command-line option, which removes the outermost quotation marks from each output value that is a JSON string.
出于您的目的,使用 -c 命令行选项可能会有所帮助,以确保每个 JSON 输出值都显示在一行中。您可能还想使用 -r 命令行选项,它会从每个 JSON 字符串输出值中删除最外层的引号。
For further variations, please see the jq FAQ https://github.com/stedolan/jq/wiki/FAQ, e.g. the question:
有关进一步的变化,请参阅 jq 常见问题解答https://github.com/stedolan/jq/wiki/FAQ,例如问题:
Q: How can a stream of JSON texts produced by jq be converted into a bash array of corresponding values?
问:jq 生成的 JSON 文本流如何转换为对应值的 bash 数组?
回答by agc
Experimental conversion of quoted OP input, (tv.dat), to a series of bash
variables, (and an array). The jq
code is mostly borrowed from here and there, but I don't know how to get jq
to unroll an array within an array, so the sed
code does that, (that's only good for one level, but so are bash
arrays):
带引号的 OP 输入(tv.dat)到一系列bash
变量(和一个数组)的实验转换。该jq
代码主要是从这里借来的,有,但我不知道怎么去jq
解开一个阵列内的阵列,所以sed
代码这样做,(这只是一个水平不错,而且还有bash
阵列):
jq -r ".[] | to_entries | map(\"DAT_\(.key) \(.value|tostring)\") | .[]" tv.dat |
while read a b ; do echo "${a,,}='$b'" ; done |
sed -e '/{.*}/s/"\([^"]*\)":/[]=/g;y/{},/() /' -e "s/='(/=(/;s/)'$/)/"
Output:
输出:
dat_absolutenumber='51'
dat_airedepisodenumber='6'
dat_airedseason='4'
dat_airedseasonid='680431'
dat_dvdepisodenumber='6'
dat_dvdseason='4'
dat_episodename='We Will Rise'
dat_firstaired='2017-03-15'
dat_id='5939660'
dat_language=([episodeName]="en" [overview]="en")
dat_lastupdated='1490769062'
dat_overview='Clarke and Roan must work together in hostile territory in order to deliver an invaluable asset to Abby and her team.'