[英]Iterate through JSON objects with jq in shell script
我正在尝试使用jq在shell脚本程序中解析json文件。
JSON结构如下所示:
{
"items":[
{
"playlists":[
{
"title":"Level One Title",
"courses":[
{
"title":"Level One Course One Title",
"lessons":[
{
"title":"lesson 1 title",
"url":"lesson 1 url"
},
{
"title":"lesson 2 title",
"url":"lesson 2 url"
}
]
},
{
"title":"Level One Course Two Title",
"lessons":[
{
"title":"lesson 1 title",
"url":"lesson 1 url"
},
{
"title":"lesson 2 title",
"url":"lesson 2 url"
}
]
}
]
},
{
"title":"Level Two Title",
"courses":[
{
"title":"Level Two Course One Title",
"lessons":[
{
"title":"lesson 1 title",
"url":"lesson 1 url"
},
{
"title":"lesson 2 title",
"url":"lesson 2 url"
}
]
},
{
"title":"Level Two Course Two Title",
"lessons":[
{
"title":"lesson 1 title",
"url":"lesson 1 url"
},
{
"title":"lesson 2 title",
"url":"lesson 2 url"
}
]
}
]
}
]
}
]
}
因为我是iOS开发人员,所以我写了一段Swift代码的模拟片段,可以实现我想要的功能。 看起来像这样:
for level in levels {
let title = level["title"]
//TODO: create a folder with title and set as pwd
for course in level["courses"] {
let courseTitle = course["title"]
//TODO: create a folder with title and set as pwd
for lesson in course["lessons"] {
let title = lesson["title"]
let videoURL = lesson["url"]
//TODO: download video in current folder with title
}
}
}
levels
是Dictionaries
Array
, level
是这些Dictionaries
。 每级包含一个Array
的courses
,其中的每一个是一个Dictionary
,含有Array
的lesson
词典。
来自Swift,我发现jq的语法非常混乱,尤其是将函数返回值分配给变量。 这是我走了多远:
levels=$(jq ".items[0].playlists" data.json)
for level in $levels
do
title=$($level | jq ".title")
echo $title
done
这似乎根本不起作用。 我猜我在这里使用for循环的逻辑是完全错误的。 任何想法如何做到这一点?
将标题和URL提取到不同的shell变量中的代码如下所示:
jq_program='
.items[].playlists[] # we only care about playlist contents
| .title as $level_title # store the level title before recursing
| .courses[] # ...into elements of the array in .courses...
| .title as $course_title # repeat to store the course title
| .lessons[] # ...before recursing into the lesson...
# ...and emitting the stored level and course titles, plus the lesson title and url
| [$level_title, $course_title, .title, .url] | @tsv
'
while IFS=$'\t' read -r level_title course_title lesson_title lesson_url <&3; do
mkdir -p -- "$level_title/$course_title"
## For test purposes, just store the URL in the file
printf '%s\n' "$lesson_url" >"$level_title/$course_title/$lesson_title"
## If we had real data, we might instead be running something like:
# curl -o "$level_title/$course_title/$lesson_title" "$lesson_url"
done 3< <(jq -r "$jq_program" <input.json)
在这里,我们让jq
进行递归并发出平坦(制表符分隔的)列表的工作,并且正在bash中读取该列表。 出于明显的原因,这仅在内容不能包含标签时才有效; 如果您需要使用任意字符串(在bash可以存储的范围内),则可以从jq
生成以NUL分隔的输出,但是需要在stedolan / jq#1271中讨论的解决方法之一。
请参阅BashFAQ#1,讨论我们在此处使用的从jq
的输出中读取制表符分隔数据的技术。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.