Skip to the content.

jq 中文手册(v1.5)

本文档为 stedolan.github.io/jq/manual/v1.5/ 的中文翻译,旨在推广 jq 的国内使用 (翻译说明)

jq 程序就像一个过滤器:接收输入,并产生输出。有许多内置的过滤器,提取一个对象的特定字段、或是把数字转成字符串,或是大量的其他的标准任务。

可以通过多种方法结合这些过滤器 - 可以用管道将一个过滤器的输出连到另一个的输入上,或者是把一个过滤器的输出收集到一个数组里。

一些过滤器产生多个结果,比如就有一个可以展开输入的数组把每个元素都给出来的的过滤器,用管道把这个连到第二个过滤器上就使第二个过滤器在数组的每一个元素上作用一遍。通常在其他语言里用循环或者迭代的任务在jq中通过结合过滤器来完成。

切记每个过滤器都有一个输入和一个输出。即使像”hello”或者42这样的常量都是过滤器-他们接受输入但是只产生同样的常量作为输出罢了。操作符可以结合两个过滤器,比如 , 一般是给两个过滤器同样的输入,并把结果连接起来。所以你可以实现一个求平均过滤器,即add/length - 把输入数组分给add过滤器和length过滤器,然后做了一个除法。

但是这个可能有些超前了。:),接着看一些简单的:

内容:

调用jq

jq 过滤器运行在JSON 数据流上。jq的输入被解析为一系列由空格分隔的JSON 值,它们一次一个地通过jq 的过滤器。过滤器的输出被写入标准输出,再次作为一系列由空格分隔的JSON数据。

注意: 注意: 一定要当心 shell 的 quote 规则。作为一般规则,最好总是为 jq 程序带上引号(使用单引号),因为太多对jq有特殊意义的字符也是 shell 的元字符。比如 jq "foo",在大多数的Unix shell中将会失败,因为这会被当做jq foo 来执行,而通常会报 foo is not defined 这样的错误。当使用Windows 的命令行 shell(cmd.exe)时,最好在命令行上给 jq 程序带上双引号(而不是-f program-file选项),不过这样的话,jq 程序里面的双引号就需要反斜杠转义了。

你可以使用一些命令行选项来影响 jq 如何读写输入和输出:

基本过滤器

.

绝对最简单(也最平常)的过滤器是 `.`,这是一个接收输入并原样输出的过滤器。

因为jq默认会优美打印所有的输出,这个小程序可以用来格式化一些JSON输出,比如curl

Example

  jq ‘.’
Input “Hello, world!”
Output “Hello, world!”

.foo,.foo.bar

最简单的有用过滤器是 .foo。给定一个JSON Object (即字典或hash)做输入,它会给出”foo”键的值,如果没有这个key则给出null.

如果键里含有关键字符,就要用双引号括起来,比如:.”foo$”.

一个形如.foo.bar的过滤器是.foo|.bar的等效写法。

Examples

        jq  '.foo'
--------------------
Input   {"foo": 42, "bar": "less interesting data"}
Output  42
        jq  '.foo'
--------------------
Input   {"notfoo": true, "alsonotfoo": false}
Output  null
        jq  '.["foo"]'
--------------------
Input   {"foo": 42}
Output  42

.foo?

就跟.foo差不多,但是当.不是一个数组或一个对象而报错时,不会输出。

Examples

        jq  '.foo?'
--------------------
Input   {"foo": 42, "bar": "less interesting data"}
Output  42
        jq  '.foo?'
--------------------
Input   {"notfoo": true, "alsonotfoo": false}
Output  null
        jq  '.["foo"]?'
--------------------
Input   {"foo": 42}
Output  42
        jq  '[.foo?]'
--------------------
Input   [1,2]
Output  []

.[<string>],.[2],.[10:15]

也可以使用类似 .["foo"] 的语法来查找 JSON Object 的一些元素 (上面的 .foo 是这个的一个速记版本)。如果 key 是数字的话,这种用法在 array 的情况下也可以有效。array 是以 0 为基的(类似 javascript),因此 .[2] 返回 array 的第三个元素。

.[10:15] 这种语法可以用来返回一个数组的子数组,或者一个字符串的子字符串。.[10:15] 返回的数组长为 5,包含了索引从 10(包含)到 15(不包含)的元素。索引可以是负数的(这种情况下会从 array 的尾部开始倒着计数) 或者可以忽略(这种情况下指向数组的头部或者尾部)。

.[2] 这种语法用来返回数组的指定索引的元素。负索引也是可以的,-1 表示最后一个元素,-2 表示倒数第二个元素,以此类推。

.foo 这种语法仅对简单的 key 有效,即 key 仅包含字母或数字字符(alphanumeric)。 .[<string>] 这种语法可以对包含特殊字符的 key 有效,诸如冒号或者点号。比如 .["foo::bar"].["for.bar"] 可以起效,而.foo::bar.foo.bar 就不行。

? 操作符(“operator”) 也可以在这种切片操作(slice operator)下使用。例如 .[10:15]? 可以在输入是可进行切片操作(slice-able)的时候输出一些值。

Examples

        jq '.[0]'
--------------------
Input   [{"name":"JSON", "good":true}, {"name":"XML", "good":false}]
Output  {"name":"JSON", "good":true}
        jq '.[2]'
--------------------
Input   [{"name":"JSON", "good":true}, {"name":"XML", "good":false}]
Output  null
        jq '.[2:4]'
--------------------
Input   ["a","b","c","d","e"]
Output  ["c", "d"]
        jq '.[2:4]'
--------------------
Input   "abcdefghi"
Output  "cd"
        jq '.[:3]'
--------------------
Input   ["a","b","c","d","e"]
Output  ["a", "b", "c"]
        jq '.[-2:]'
--------------------
Input   ["a","b","c","d","e"]
Output  ["d", "e"]
        jq '.[-2]'
--------------------
Input   [1,2,3]
Output  2

.[]

如果使用 .[index] 这种语法,但完全省略 index,他就会返回 array 的 所有 元素。

对于输入 [1,2,3] 运行 .[] 就会生出 3 个独立的结果,而不是一个单个数组。

也可以在 object 上使用它,它将返回 object 的所有 value

Examples

        jq '.[]'
--------------------
Input   [{"name":"JSON", "good":true}, {"name":"XML", "good":false}]
Output  {"name":"JSON", "good":true}
        {"name":"XML", "good":false}

        jq '.[]'
--------------------
Input   []
Output
        jq '.[]'
--------------------
Input   {"a": 1, "b": 1}
Output  [1, 1]

.[]?

类似 .[], 不过当 . 不是 array 或者 object 是不会输出 errors Like .[], but no errors will be output if . is not an array or object.

,

如果用逗号分隔两个过滤器,输入就会被每个过滤器处理,并依次输出多个结果: 首先是第一个过滤器的生成的所有输出,然后是第二个过滤器的生成的所有输出。 如 .foo, .bar 生成 “foo” 字段和 “bar” 字段的值。

Examples

        jq '.foo, .bar'
--------------------
Input   {"foo": 42, "bar": "something else", "baz": true}
Output  [42, "something else"]
        jq '.user, .projects[]'
--------------------
Input   {"user":"stedolan", "projects": ["jq", "wikiflow"]}
Output  ["stedolan", "jq", "wikiflow"]
        jq '.[4,2]'
--------------------
Input   ["a","b","c","d","e"]
Output  ["e", "c"]

|

| 运算符结合左右两个过滤器 Filter, 把左边的输出 output 投递到右边的输入 input。如果你用过 Unix shell 的管道 pipe, |几乎和它是一样的。

如果左边的过滤器产生多个结果,则将为每个结果运行右侧过滤器。 所以表达式.[] | .foo检索输入数组里每个元素的 “foo” 字段。

Examples

        jq '.[] | .name'
--------------------
Input   [{"name":"JSON", "good":true}, {"name":"XML", "good":false}]
Output  ["JSON", '"XML"']

Types and Values

jq 支持与 JSON 相同的一组数据类型集合 – 数字 numbers、 字符串 strings、布尔值 booleans、数组 arrays、对象 objects(在 JSON 中称做是仅有字符串键的哈希值 hashes)和 null 。

布尔值 booleans 、空值 null、字符串 strings 和数字 numbers 的书写方式与在 JavaScript 中相同。和 jq 中其他的内容一样,这些简单的值也被看做接收一个输入, 并且产生一个输出。如, 42 是一个合法的 jq 表达式, 忽略接收的输入, 并输出 42。

数组构造(array) - []

与 JSON 一样,[] 用于构造数组,如 [1,2,3]。 数组的元素可以是任何 jq 表达式。所有表达式产生的所有结果都被收集到一个大数组中。你可以使用它从已知数量的值中构造一个数组(如 [.foo, .bar, .baz] )或将过滤器的所有结果”收集”到一个数组中(如 [.items[].name]

一旦你理解了 , 运算符,你就可以从不同的角度看待 jq 的数组语法:表达式 [1,2,3] 不是使用逗号分隔数组的内置语法,而是在对表达式 1,2,3(输出 3 个值) 应用 [] 运算符(收集结果)。

如果你有一个过滤器 X 产生四个结果,那么表达式 [X] 将产生一个结果,即一个包含四个元素的数组。

Examples

        jq '[.user, .projects[]]'
-------------------------------------
Input   {"user":"stedolan", "projects": ["jq", "wikiflow"]}
Output  ["stedolan", "jq", "wikiflow"]

Objects - {}

与 JSON 一样,{} 用于构建对象(又叫字典 dictionary 或哈希 hash),如:{"a": 42, "b": 17}

如果 Key 是 “合理的(sensible)” (由所有字母字符组成),则引号可以省略。Value 可以是任何表达式(如果比较复杂, 可以使用括号包起来),表达式会将 {} 表达式的输入作为输入(每个过滤器都有一个输入和输出)。

{foo: .bar}

如果输入是 {"bar":42, "baz":43}, 那么表达式的输出为 {"foo": 42}

可以用来筛选一个 object 的特定字段:如果输入对象有 “user”、”title”、”id”、”content” 字段,而只需要 “user”、”title”,则可以这样写

{user: .user, title: .title}

因为这种用法很常见,所以有一个快捷语法:{user, title}

如果其中一个表达式生成多个结果,那么表达式将生成多个词典。如果输入是

{"user":"stedolan","titles":["JQ Primer", "More JQ"]}

那么表达式

{user, title: .titles[]}

将会生成输出

{"user":"stedolan", "title": "JQ Primer"}
{"user":"stedolan", "title": "More JQ"}

使用括号包裹 Key ,意味着它将被当做表达式来计算 key 。使用与上述相同的输入,

表达式

{(.user): .titles}

会输出

{"stedolan": ["JQ Primer", "More JQ"]}

Examples

        jq '{user, title: .titles[]}'
-------------------------------------
Input   {"user":"stedolan","titles":["JQ Primer", "More JQ"]}
Output  {"user":"stedolan", "title": "JQ Primer"}
        {"user":"stedolan", "title": "More JQ"}
        jq '{(.user): .titles}'
-------------------------------------
Input   {"user":"stedolan","titles":["JQ Primer", "More JQ"]}
Output  {"stedolan": ["JQ Primer", "More JQ"]}

TODO


- program: ‘@html “Anonymous said: (.)”’

input: ‘“”’

output: [“Anonymous said: <script>alert("lol hax");</script>”]

      - program: '@sh "echo \(.)"'
        input: "\"O'Hara's Ale\""
        output: ["\"echo 'O'\\\\''Hara'\\\\''s Ale'\""]

  - title: "Dates"
    body: |

      jq provides some basic date handling functionality, with some
      high-level and low-level builtins.  In all cases these
      builtins deal exclusively with time in UTC.

      The `fromdateiso8601` builtin parses datetimes in the ISO 8601
      format to a number of seconds since the Unix epoch
      (1970-01-01T00:00:00Z).  The `todateiso8601` builtin does the
      inverse.

      The `fromdate` builtin parses datetime strings.  Currently
      `fromdate` only supports ISO 8601 datetime strings, but in the
      future it will attempt to parse datetime strings in more
      formats.

      The `todate` builtin is an alias for `todateiso8601`.

      The `now` builtin outputs the current time, in seconds since
      the Unix epoch.

      Low-level jq interfaces to the C-library time functions are
      also provided: `strptime`, `strftime`, `mktime`, and `gmtime`.
      Refer to your host operating system's documentation for the
      format strings used by `strptime` and `strftime`.  Note: these
      are not necessarily stable interfaces in jq, particularly as
      to their localization functionality.

      The `gmtime` builtin consumes a number of seconds since the
      Unix epoch and outputs a "broken down time" representation of
      time as an array of numbers representing (in this order): the
      year, the month (zero-based), the day of the month, the hour
      of the day, the minute of the hour, the second of the minute,
      the day of the week, and the day of the year -- all one-based
      unless otherwise stated.

      The `mktime` builtin consumes "broken down time"
      representations of time output by `gmtime` and `strptime`.

      The `strptime(fmt)` builtin parses input strings matching the
      `fmt` argument.  The output is in the "broken down time"
      representation consumed by `gmtime` and output by `mktime`.

      The `strftime(fmt)` builtin formats a time with the given
      format.

      The format strings for `strptime` and `strftime` are described
      in typical C library documentation.  The format string for ISO
      8601 datetime is `"%Y-%m-%dT%H:%M:%SZ"`.

      jq may not support some or all of this date functionality on
      some systems.

    examples:
      - program: 'fromdate'
        input: '"2015-03-05T23:51:47Z"'
        output: ['1425599507']

      - program: 'strptime("%Y-%m-%dT%H:%M:%SZ")'
        input: '"2015-03-05T23:51:47Z"'
        output: ['[2015,2,5,23,51,47,4,63]']

      - program: 'strptime("%Y-%m-%dT%H:%M:%SZ")|mktime'
        input: '"2015-03-05T23:51:47Z"'
        output: ['1425599507']