我正在尝试使用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
是Array
Dictionaries
,level
是Dictionaries
之一。每个级别都包含Array
courses
个Dictionary
,每个级别为Array
,其中包含lesson
个levels=$(jq ".items[0].playlists" data.json)
for level in $levels
do
title=$($level | jq ".title")
echo $title
done
词典。
来自Swift,我发现jq的语法非常混乱,特别是将函数返回值赋给变量。这是我走了多远:
groups = (1, 2, 3, 4)
attrs = ('Referencia', 'Concepto', 'Cantidad', 'Precio', 'Descuento')
idx = (15, 22, 29, 38)
for group, index in zip(groups, idx):
for i, attr in enumerate(attrs):
getattr(self, 'line' + attr + str(i)).setText(utilidades.ensure_its_str(registro[i+index]))
这似乎根本不起作用。我想我的逻辑使用for循环在这里是完全错误的。有任何想法如何做到这一点?
答案 0 :(得分:3)
将标题和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
的输出中读取制表符分隔的数据。