idea: add a function pathexpr to convert a path array representation to a path expression.
Paths, such as returned by path( ... ), would in some cases be more readable and usable after converting to a path expression.
def pathexpr:
map(
if type == "number" then
"[\(tostring)]"
else
"."+.
end
) | join("")
;
I'm using this pathexpr and thought it might be a nice addition to jq for general use.
An example
The path( ... ) function is really nice to search through lots of JSON files for a specific value.
For example:
jq 'path(..|select(contains("127.0.0.1")?))' *.json
[
"other",
0,
"data",
0,
51,
"data"
]
[
"other",
1,
"data",
0,
6,
"data"
]
...
The output of this command contains all paths that contain the text "127.0.0.1". Using the pathexpr function I can create very useful outputs. The resulting lines can even be copy-pasted to quickly run another jq to show the actual value in that file at that path:
$ jq -r 'include "funcs"; path(..|select(contains("127.0.0.1")?)) | pathexpr+" "+input_filename' *.json
.other[0].data[0][51].data data_166.json
.other[1].data[0][6].data data_195.json
.other[1].data[0][1207].data data_195.json
.other[1].data[0][186].data data_61.json
.other[1].data[0][921].data data_18.json
$ jq .other[1].data[0][921].data data_18.json
"service running on 127.0.0.1"
Edit: improved readability of pathexpr a little
Better idea: define pathexpr so that it produces strings corresponding to jq's "dot" notation, i.e. that can be used in jq programs.
Here (hopefully) is such a def:
def pathexpr:
reduce .[] as $k ("";
. + ($k | if type == "number" then "[\(.)]"
elif test("[^a-zA-Z0-9_]") then "[\"\(.)\"]"
else "." + $k
end))
| if startswith(".") then . else "." + . end ;
Example:
Since {"a": {"b.c": {"d": 99}}} | .a["b.c"].d we want
["a","b.c","d"] | pathexpr
to emit .a["b.c"].d.
Hi,
The function doesn't work with non ascii keys.
I use following function for the same purpose in my project jq-front.
def path2pexp($v):
$v | reduce .[] as $segment (""; . + ($segment
|if type == "string" then ".\"" + . + "\""
else "[\(.)]" end));
Most helpful comment
Better idea: define pathexpr so that it produces strings corresponding to jq's "dot" notation, i.e. that can be used in jq programs.
Here (hopefully) is such a def:
Example:
Since
{"a": {"b.c": {"d": 99}}} | .a["b.c"].dwe wantto emit
.a["b.c"].d.