jq语言
编程范型 | 纯函数式, 面向JSON处理, 隐式 |
---|---|
設計者 | Stephen Dolan |
发行时间 | 2012年8月21日 |
当前版本 |
|
實作語言 | jq: C gojq: Go jaq: Rust jqjq: jq |
系统平台 | 跨平台[a] |
操作系统 | 跨平台[b] |
許可證 | MIT[c] |
網站 | jqlang |
啟發語言 | |
JSON, sed, Icon |
jq是高级领域特定的词法作用域的函数式编程语言,在其中所有JSON值都是常量。jq支持回溯和管理JSON数据的无限长字串流。它有关于Icon和Haskell编程语言。此语言支持基于名字空间的模块系统,并对闭包有一定支持。特别是,函数和泛函表达式可以用作其他函数的参数。
历史
[编辑]jq由Stephen Dolan创建并在2012年10月发行[4][5] 。它被设计为“针对JSON数据的sed类似者”[6]。在jq版本1.5中增加支持了正则表达式。
针对jq的叫做yq的“包装器”[7],增加支持了YAML、XML和TOML。它首次发行于2017年[8]。
用Go实现的gojq最初发行于2019年[9],gojq显著的扩展jq包括了支持YAML。
用Rust实现的jaq,其项目目标是更快速和更准确的jq实现,仍保持与jq在大多数情况下的兼容性。在2024年3月在其目标中排除了jq的特定高级特征,比如模块、SQL风格算子和给非常大JSON文档的串流解析器[10]。
用jq实现的jqjq,最初发行于2022年。jqjq显著的可以运行自身,拥有REPL并支持eval
。
用法
[编辑]命令行用法
[编辑]jq典型的用于命令行,并可以协作于其他命令行实用工具,比如curl。下面的例子展示如何将curl
命令的输出通过管道接转到jq过滤器,从而确定同这个Wikipedia页面关联的范畴名字:
$ URL='https://zh.wikipedia.org/w/api.php?action=parse&page=Jq%E8%AF%AD%E8%A8%80&format=json'
$ curl -s ${URL} | jq '.parse.categories[]."*"'
这个流水线产生的输出,由JSON字符串的串流组成,它们是:
"小寫標題"
"CS1英语来源_(en)"
"动态类型编程语言"
"函数式编程语言"
"2012年建立的程式語言"
"数据查询语言"
"2012年软件"
上述curl
命令对这个页面使用了MediaWiki API来产生JSON响应。管道|
允许curl
的输出由jq来访问,它是标准的Unix shell机制[11]。
展示的jq过滤器是如下jq流水线的简写:
.["parse"] | .["categories"] | .[] | .["*"]
这对应于curl
调用所产生的嵌套JSON结构。注意jq流水线的构造方式,同Unix风格流水线一样,采用|
字符。
嵌入式用法
[编辑]C语言和Go实现二者都提供函数库,使得jq函数可以嵌入到其他应用和编程环境值中。
例如,gojq已经集成于SQLite,故而jq
函数可以在其SQL语句中获得到[12]。这些函数被标记为“确定性的”[13],故而可以被用在CREATE INDEX
命令中[14]。
运算的模态
[编辑]jq缺省的充当针对JSON输入的“串流编辑器”,非常像被当作多行文本的“串流编辑器”的sed实用工具。但是jq有一些其他运算模态:
- 它可以将来自一个或多个来源的输入当作文本的诸行;
- 它可以将来自特定来源的输入的串流收集到一个JSON数组之中;
- 它可以使用所谓的“串流解析器”解析其输入,产生针对所有“叶子”路径的
[path, value]
数组的串流。
“串流解析器”(streaming parser),在一个或多个JSON输入太大无法载入内存之时特别有用,因为它需求的内存典型的相当小。例如,对于任意大的JSON对象的数组,峰值内存需求不比处理最大顶层对象所需要的多出很多。
这些运算模态可以在特定限制下组合起来。
语法和语义
[编辑]类型
[编辑]所有JSON值自身是jq中的值,它们从而有在下列表格中展示的类型[15]。gojq和jaq实现区分整数和非整数的数。gojq实现支持无界精度整数算术,同于jq采用Haskell的最初实现。
类型 | 例子 |
---|---|
"number" |
|
"string" |
|
"boolean" |
|
"array" |
|
"object" |
|
"null" |
|
null
是一个值[16],就像任何其他JSON标量一样;它不是指针或空指针。nan
(对应于NaN)和infinite
(参见IEEE 754),是仅有的两个不是JSON值的jq标量。
形式
[编辑]有用于函数创建、条件、串流归约和模块系统的特殊语法形式。
过滤器
[编辑]jq是面向JSON的编程语言,使用|
符号来连接过滤器形成流水线。例如:
$ jq -n '[1,2] | add'
3
这里的JSON数组是求值为数组的一个jq过滤器。
尽管类似于Unix流水线,jq流水线允许将到来数据如同并行的发送到在|
右手端的多于一个接收者。例如,程序add/length
将计算数组中数的平均,故而:
$ jq -n '[1,2] | add/length'
1.5
$ jq -nc '[1,2] | [length, add, add/length]'
[2,3,1.5]
点号.
可以被用来在右手端定义一个附着点(attachment point),例如:
$ jq -nc '1 | [., .]'
[1,1]
$ jq -n '2 | pow(.; .)'
4
$ jq -c '. as $n | [1,0,1] | [recurse(select(.[0] < $n) | [.[0]+1, .[2], .[1]+.[2]]) | .[2]]'
1
[1]
2
[1,1]
3
[1,1,2]
6
[1,1,2,3,5,8]
下面将其定义为新的命名过滤器:
def fib: . as $n
| [1,0,1]
| [recurse(select(.[0] < $n)
| [.[0]+1, .[2], .[1]+.[2]])
| .[2]];
下面的例子展示如何定义命名的参数化的过滤器,它格式化从2到36含二者的任何基数的整数:
# Use gojq for infinite precision integer arithmetic
def tobase($b):
def digit: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[.:.+1];
def mod: . % $b;
def div: ((. - mod) / $b);
def place_values: recurse(select(. >= $b) | div) | mod;
select(2 <= $b and $b <= 36)
| [place_values | digit] | reverse | add;
将其保存入tobase.jq
文件,接着使用这个函数:
$ jq 'include "./tobase"; tobase(16)'
17
"11"
下一个例子展示使用生成器于经典的“SEND+MORE=MONEY”覆面算游戏:
def send_more_money:
def choose(m;n;used): ([range(m;n+1)] - used)[];
def num(a;b;c;d): 1000*a + 100*b + 10*c + d;
def num(a;b;c;d;e): 10*num(a;b;c;d) + e;
first(
1 as $m
| 0 as $o
| choose(8;9;[]) as $s
| choose(2;9;[$s]) as $e
| choose(2;9;[$s,$e]) as $n
| choose(2;9;[$s,$e,$n]) as $d
| choose(2;9;[$s,$e,$n,$d]) as $r
| choose(2;9;[$s,$e,$n,$d,$r]) as $y
| select(num($s;$e;$n;$d) + num($m;$o;$r;$e) ==
num($m;$o;$n;$e;$y))
| [$s,$e,$n,$d,$m,$o,$r,$e,$m,$o,$n,$e,$y]);
send_more_money
将其保存入send_more_money.jq
文件,接着使用这个函数:
$ jq -nc -f ./send_more_money.jq
[9,5,6,7,1,0,8,5,1,0,6,5,2]
解析表达式文法
[编辑]在jq和解析表达式文法(PEG)形式化之间有密切关联[17]。这种关联源于下列表格中展示的PEG七个基本运算与jq构造之间的等价性。
PEG运算名字 | PEG表示法 | jq运算或def |
---|---|---|
序列 | e1 e2
|
e1 | e2
|
有序选择 | e1 / e2
|
e1 // e2
|
零或多个 | e*
|
def star(E): (E | star(E)) // . ;
|
一或多个 | e+
|
def plus(E): E | (plus(E) // . );
|
可选 | e?
|
def optional(E): E // .;
|
与断言 | &e
|
def amp(E): . as $in | E | $in;
|
非断言 | !e
|
def neg(E): select( [E] == [] );
|
移植和变体
[编辑]gojq是“纯Go”实现。还有Rust实现的jq方言叫做jaq[10],它规定了指称语义[18]。
注释
[编辑]参考书目
[编辑]- Janssens, Jeroen. Data Science at the Command Line. O'Reilly Media. 2021. ISBN 9781492087885 (英语).
- Janssens, Jeroen. Data Science at the Command Line: Facing the Future with Time-Tested Tools. O'Reilly Media. 2014. ISBN 9781491947807 (英语).
- Marrs, Tom. JSON at Work: Practical Data Integration for the Web. O'Reilly Media. 2017. ISBN 9781491982419 (英语).
引用
[编辑]- ^ Release jq 1.7.1.
- ^ 2.0 2.1 2.2 Download jq. jq. [January 6, 2023].
- ^ Initial · jqlang/Jq@eca89ac. GitHub.
- ^ Janssens 2014.
- ^ jq. jq. [January 6, 2023].
- ^ like sed. (原始内容存档于2013-04-14).
- ^ yq
- ^ Release v2.0.0 · kislyuk/yq. GitHub.
- ^ Release v0.0.1 · itchyny/gojq. GitHub.
- ^ 10.0 10.1 01mf02/jaq: A jq clone focussed on correctness, speed, and simplicity. GitHub. [March 6, 2024].
- ^ Tutorial. jq. [January 6, 2023].
- ^ sqlite_jq. GitHub.
- ^ "deterministic"
- ^ FAQ. GitHub.
- ^ Manual. jq. [January 6, 2023].
- ^ [https://www.json.org/json-en.html null
- ^ PEG. PEG.
- ^ Färber, Michael. Denotational Semantics and a fast interpreter for jq. 2023. arXiv:2302.10576 [cs.LO].
外部链接
[编辑]- jq homepage
- gojq - the Pure Go implementation
- jaq - the Rust implementation
- jqjq - the jq implementation
- jq FAQ
- Awesome jq - curated listing of jq-related resources
- The jq Programming Language page on the Rosetta Code comparative programming tasks project site