我使用以下代码从巨大的json格式文件中获取数据。
_ITEM_L1=`cat json.list | jq .item[].length | wc -l`
for (( i=0;i<$_ITEM_L1;i++ ));
do
_ITEM_L2=`cat json.list | jq .item[$i].item[].length | wc -l`
for (( j=0;j<$_ITEM_L2;j++ ));
do
_API_NAME=`cat json.list | jq .item[$i].item[$j].name`
_API_URL=`cat json.list | jq .item[$i].item[$j].request.url.raw`
echo $_API_NAME
echo $_API_URL;
done;
done
起初,我认为它只有2个级别,但是运行脚本时发现它超过2个级别,可能是3或4甚至5或更多。 所以我的问题是在开始迭代之前如何知道json文件中有多少级?
item0
|
item0
|
item0
name:
url:
item1
name:
url:
item2
name:
url:
item1
|
item0
|
item0
name:
url:
item1
name:
url:
item1
|
item0
name:
url:
item1
name:
url:
item2
name:
url:
item1
|
item0
name:
url:
item1
name:
url:
item2
name:
url:
.
.
.
.
.
.
答案 0 :(得分:0)
更好的设计不会要求,您不必知道文件中有多少层嵌套深度,并且绝对不会调用{{1} }一遍又一遍! ({jq
是一种完善的编程语言-它可以自行循环,并且仅通过一次jq调用处理整个文件,而不是使用不同的过滤器一遍又一遍地处理,效率要高得多)。
让我们从一个具体的示例输入开始:
jq
要将其转换为扁平的名称/ URL对对,可以使用:
{
"item0": {
"item0a": {
"item0aA": {
"name": "foo",
"url": "bar"
},
"item0aB": {
"name": "baz",
"url": "qux"
}
}
},
"item1": {
"name": "qux",
"url": "quux"
}
}
将作为输出发出:
jq -r '.. | objects | select(.name? != null) | [ .name, .url ] | @tsv'
...您可以在bash中轻松对其进行迭代:
foo bar
baz qux
qux quux
了解其工作原理:
while IFS=$'\t' read -r name url; do
echo "Read name $name and url $url"
done < <(jq -r '.. | objects | select(.name? != null) | [ .name, .url ] | @tsv' <json.list)
是jq的递归下降算子。..
忽略不是对象的东西。objects
仅过滤具有名称的对象。 (可以类似地只过滤具有相同网址的对象)。.name? != null
将输出以制表符分隔的值形式。@tsv
将输入行读入变量IFS=$'\t' read -r name url
和name
,并用制表符将它们分开。