A mix between grep and jq
Look for partial text, and wildcard matches in JSON files.
Because jq forces you to know the entire path, and grep makes the match lose its JSON context.
If you want to make suggestions, discussion is welcomed in the issues
You need cargo to install jgrep. If you don't have it, you can install it with rustup
To install jgrep, just run
cargo install jgrep
We will use the following JSON for all the examples:
{
"items": [
{
"id": 1,
"name": "Lorem",
"active": true,
"meta": {
"rating": 4.7,
"author": { "name": "John", "verified": false }
}
},
{
"id": 2,
"name": "Ipsum",
"active": false,
"meta": {
"rating": 3.9,
"author": { "name": "Jane", "verified": true }
}
}
]
}
Jgrep uses a very simple query language, based on the JSON path syntax, and admitting wildcards (* and ?) for keys and values.
jgrep 'Jane' filename
#> .items[1].meta.author.name: "Jane"
Will look for all the occurrences of 'Jane', in keys or values, and it will return the path to it.
You can also look for keys only, by putting the keys before a colon (:), or starting it with a dot (.):
jgrep 'author:' filename
# or
jgrep '.meta.author' filename
#> .items[0].meta.author: {
#> "name": "John",
#> "verified": false
#> }
#> .items[1].meta.author: {
#> "name": "Jane",
#> "verified": true
#> }
Or for values only, by putting the value after a colon:
jgrep ': true' filename
#> .items[0].active: true
#> .items[1].meta.author.verified: true
Or for values and keys, having the key before a colon and the value after it:
jgrep '.rating: 4.7' filename
#> .items[0].meta.rating: 4.7
And you can use wildcards:
jgrep '.name: J*n*' filename
#> .items[0].meta.author.name: "John"
#> .items[1].meta.author.name: "Jane"
jgrep '.name: Jan?' filename
#> .items[1].meta.author.name: "Jane"
Wildcards work with numbers too:
jgrep '.rating: 4.*' filename
#> .items[0].meta.rating: 4.7
Prints just the matching key, value, or key-value pair. Useful for piping or processing the raw matched data.
jgrep '.author' filename -o
#> {"name":"John","verified":false}
#> {"name":"Jane","verified":true}
If you want to see the whole matched json, not just the path to the matched part, use the --json
(-j
) flag.
The path to the current match will be displayed in a different color, if the terminal supports it.
jgrep '.rating' filename -j
#> {
#> "items": [
#> {
#> "meta": {
#> "rating": 4.7
#> }
#> },
#> {
#> "meta": {
#> "rating": 3.9
#> }
#> },
#> ]
#> }
Like for grep, --context
(-C
) displays information around the match. In jgrep, each context prints one previous level of the JSON object.
The path to the current match will be displayed in a different color, if the terminal supports it.
jgrep 'Jane' filename -C 1
#> .items[1].meta.author: {"name":"Jane","verified":true}
Also works with the -json
(-j
) flag, increasing the context level:
jgrep "Jane" filename -C 2 -j
#> {
#> "items": [
#> {
#> "meta": {
#> "rating": 3.9,
#> "author": {
#> "name": "Jane",
#> "verified": true
#> }
#> }
#> },
#> ]
#> }
In comparison to no context:
jgrep "Jane" filename -j
#> {
#> "items": [
#> {
#> "meta": {
#> "author": {
#> "name": "Jane"
#> }
#> }
#> },
#> ]
#> }
It increases the JSON printed two levels backwards (in this case, with -C 2
)