如何将 jq 中的参数传递给 ~/.jq dotfile 中定义的函数? 目标源 JSON我用作测试的:不使用自定义函数的例子~/.jq 中的函数平台

问题描述

目标

我正在尝试在我的 ~/.jq 中声明函数,以便它们可以重复使用。我不确定我是否有传递参数的正确语法。我已经看过 builtin.jq source 但递归飞过我的头。任何人都可以帮助澄清我在下面所做的方式是否正确?

注意我知道运行 jq <json.txt '...' 比“无用使用 cat”更有效,但为了清楚起见,我是这样写的所以所有的 jq 语法都在 RHS 上。

源 JSON(我用作测试的):

curl -s 'https://packagecontrol.io/channel_v3.json' >json.txt

不使用自定义函数的例子

这是在命令行上执行的jq代码

$ cat json.txt |
jq -c --arg q "colorhelper" 'paths as $p |
  select(getpath($p)?|test($q;"i")) |
  $p'

==> ["packages_cache","https://packagecontrol.io/repository.json",625,"name"]...

~/.jq 中的函数

我在 grep 中定义了一个名为 ~/.jq函数

def grep($q; $f):
  paths as $p |
  select(getpath($p)?|test($q;$f)) |
  $p ;

...并这样称呼它:

$ cat json.txt | jq -c 'grep("colorhelper";"i")'
==> ["packages_cache","name"]...

“它有效”,但我想知道如何声明函数,以便如果省略第二个参数(在本例中为 "i"),它仍然会成功。按原样,如果仅使用单个参数 (jq: error: grep/1 is not defined at <top-level>)

调用函数,则会引发错误

平台

  • macOS 11.2.1
  • jq 1.6(自制软件)
$ jq --version
jq-1.6

解决方法

您所要做的就是在 ~/.jq 中为 grep/1 添加一个合适的定义。例如,您可以添加(在 grep/2 之后):

def grep($q): grep($q; "i");

如果您希望“i”成为默认值。 (如果您愿意,您可以将默认值更改为 "",但这样您的查询将不会使用 json.txt 返回任何答案。)

示例

使用 ~/.jq 同上:

jq -c --arg q "colorhelper" 'grep($q)' json.txt
["packages_cache","https://packagecontrol.io/repository.json",625,"name"]
["packages_cache","homepage"]
["packages_cache","readme"]
["packages_cache","issues"]
["packages_cache","releases","url"]
["packages_cache",1,2,3,4,5,6,"url"]

如果您还将 grep/0 定义为 def grep: grep($q);,那么您的调用将不那么多余:

jq -c grep --arg q colorhelper json.txt

注意

将 ~/.jq 作为文件很好,但有点过时:最近版本的 jq 有一个模块系统,它倾向于假设 ~/.jq 是一个目录。

因此,如果您的 grep/1 定义在 ~/.jq/lib.jq 中,您会发现:

echo '["abc"]' | jq -c 'include "lib"; grep("a")'
[0]

类似:

echo '["abc"]' | jq -c 'import "lib" as lib; lib::grep("a")'
[0]