I'm trying to declare functions in my ~/.jq
so they can be re-used. I am not sure I've got the correct syntax for passing parameters. I've looked at the builtin.jq source but the recursion flew over my head. Can anyone help clarify if the way I've done it below is correct?
N.B. I know it's more efficient to run
jq <json.txt '...'
instead of the "useless use of cat", but for clarity I've written it that way so all the jq syntax is on the RHS.
curl -s 'https://packagecontrol.io/channel_v3.json' >json.txt
This is jq code executed on the commandline:
$ 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"]...
I defined a function named grep
in my ~/.jq
:
def grep($q; $f):
paths as $p |
select(getpath($p)?|test($q;$f)) |
$p ;
...and call it like this:
$ cat json.txt | jq -c 'grep("colorhelper";"i")'
==> ["packages_cache","https://packagecontrol.io/repository.json",625,"name"]...
"It works", but I'd like to know how to declare the function such that if the 2nd parameter is omitted ("i"
in this case), it will still succeed. As-is, an error is thrown if the function is called with only a single parameter (jq: error: grep/1 is not defined at <top-level>
)
jq
1.6 (Homebrew)$ jq --version
jq-1.6
All you have to do is add a suitable def for grep/1
in ~/.jq. For example, you could add (after grep/2
):
def grep($q): grep($q; "i");
if you want "i" to be the default. (You could change the default to be "" if you like, but then your query will not return any answers with json.txt.)
With ~/.jq as above:
jq -c --arg q "colorhelper" 'grep($q)' json.txt
["packages_cache","https://packagecontrol.io/repository.json",625,"name"]
["packages_cache","https://packagecontrol.io/repository.json",625,"homepage"]
["packages_cache","https://packagecontrol.io/repository.json",625,"readme"]
["packages_cache","https://packagecontrol.io/repository.json",625,"issues"]
["packages_cache","https://packagecontrol.io/repository.json",625,"releases",0,"url"]
["packages_cache","https://packagecontrol.io/repository.json",625,"releases",1,"url"]
["packages_cache","https://packagecontrol.io/repository.json",625,"releases",2,"url"]
["packages_cache","https://packagecontrol.io/repository.json",625,"releases",3,"url"]
["packages_cache","https://packagecontrol.io/repository.json",625,"releases",4,"url"]
["packages_cache","https://packagecontrol.io/repository.json",625,"releases",5,"url"]
["packages_cache","https://packagecontrol.io/repository.json",625,"releases",6,"url"]
If you also defined grep/0
as def grep: grep($q);
then your invocation would be a little less redundant:
jq -c grep --arg q colorhelper json.txt
Having ~/.jq as a file is fine but a bit antiquated: recent versions of jq have a module system which tends to assume ~/.jq is a directory.
So if your grep/1 definition was in ~/.jq/lib.jq, you would find:
echo '["abc"]' | jq -c 'include "lib"; grep("a")'
[0]
and similarly:
echo '["abc"]' | jq -c 'import "lib" as lib; lib::grep("a")'
[0]