繁体   English   中英

在外壳程序脚本中使用jq遍历JSON对象

[英]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
        }
    }
}

levelsDictionaries Arraylevel是这些Dictionaries 每级包含一个Arraycourses ,其中的每一个是一个Dictionary ,含有Arraylesson词典。

来自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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM