如何用jq在json中搜索?

时间:2017-09-15 14:00:55

标签: json jq

如何从下面输出duration值?

如果我搜索jq -r ".media.duration",那么我会获得nil

$ cat test.json | jq -r ".episodes[1:]" 
[
  {
    "uniqueHash": "a2dc48cd0f9",
    "startOffset": "{0}",
    "media": {
      "720p": {
        "extension": "mp4",
        "filesize": "1702",
        "duration": "00:51:55",
      },
    }
  },
  {
    "uniqueHash": "a2d0f9",
    "startOffset": "{0}",
    "media": {
      "720p": {
        "extension": "mp4",
        "filesize": "12602",
        "duration": "00:51:55",
      },
    }
  },
]

4 个答案:

答案 0 :(得分:2)

你仍然需要达到这一点;你还没有jq相当于cd或其他任何东西。您需要通过添加另一组括号来展平episodes[1:]返回的数组。此外,您跳过了分辨率级别("720p")。把这一切放在一起,这应该有效。它将在每行输出一个持续时间值,不带引号:

jq -r '.episodes[1:][].media["720p"].duration'

请注意,您无法在720p(* media.720p.duration)上使用点语法,因为该键以数字开头。

请注意,您的JSON代码段在技术上无效;严格的JSON不允许在列表末尾使用逗号。我纠正了这个并将其结构包裹起来以匹配您的查询:

{
  "episodes": [
    {},
    {
      "uniqueHash": "a2dc48cd0f9",
      "startOffset": "{0}",
      "media": {
        "720p": {
          "extension": "mp4",
          "filesize": "1702",
          "duration": "00:51:55"
        }
      }
    },
    {
      "uniqueHash": "a2d0f9",
      "startOffset": "{0}",
      "media": {
        "720p": {
          "extension": "mp4",
          "filesize": "12602",
          "duration": "00:51:55"
        }
      }
    }
  ]
}

在上面运行jq -r '.episodes[1:][]|.media["720p"].duration'会产生此输出:

00:51:55
00:51:55

答案 1 :(得分:2)

使用map()

$ cat test.json | jq -r '.episodes[1:] | map(.media["720p"].duration)'
[
  "00:51:55",
  "00:51:55"
]

由于.episodes[1:]会为您提供一个列表,因此您需要对其进行操作。 map(<selector>)就是你想要的。

或者,您可以使用.[]平整列表:

$ cat test.json | jq -r ".episodes[1:] | .[] | .media[\"720p\"].duration" 
00:51:55
00:51:55

以上解决方案假设您始终拥有720p。情况可能并非总是如此,因此您可以使用to_entries来获取所有解决方案:

$ cat test.json | jq -r ".episodes[1:] | map(.media|to_entries[]|.value.duration)"
[
  "00:51:55",
  "00:51:55"
]

答案 2 :(得分:1)

如果您只想在json树中提取任何duration值,您可以只递归并尝试提取duration丢弃空结果。

.. | objects.duration? // empty

为了更明确且仅提取duration值,您可以分析值的路径并仅选择duration值。

getpath(leaf_paths | select(.[-1] == "duration"))

答案 3 :(得分:1)

以下是使用tostream的变体。如果(略微更正的)样本数据在data.json,那么命令

$ jq -Mr ' 
    tostream                        # generate [[path],value] pairs from input
  | select(length==2) as [$p,$v]    # assign [path] to $p and value to $v
  | select($p[-1]=="duration")      # keep paths ending in "duration"
  | $v                              # emit value
' data.json

产生

00:51:55
00:51:55

这应该适用于原始JSON数据以及.media.duration样本数据子树。