TL;DR:
jq -r -R '
select(contains(" | ")) |
split(" | ") |
.[0] as $text |
(.[1] | fromjson | to_entries | .[0].value ) as $json_obj_value |
"\($text) | \($json_obj_value)"
' yourlogfile.log
Complete answer
Most people don't realize quite how powerful jq
is (though the same can be said about awk
).
As Kusalananda thoughtfully pointed out in their answer, your best friend here is the -R
flag, that will read the input line by line as json strings instead of a json object. With that we are free to treat the string within jq
only, without any need for awk
at all.
Here is how the documentation describes it as of version 1.6:
--raw-input
/ -R:
Don't parse the input as JSON. Instead, each line of text is passed to the filter as a string. If combined with --slurp
, then the entire input is passed to the filter as a single long string.
For your desired output you will also need the -r
flag, which makes it print bare strings instead of json strings in the terminal.
Again from the docs
--raw-output
/ -r
:
With this option, if the filter's result is a string then it will be written directly to standard output rather than being formatted as a JSON string with quotes. This can be useful for making jq filters talk to non-JSON-based systems.
So with that out of the way, there are a few ways to tackle this in jq
.
As EchoMike444 already answered with a more imperative way, I tried to use a different approach, which was a little more pipeliney.
jq -r -R '
select(contains(" | ")) |
split(" | ") |
.[0] as $text |
(.[1] | fromjson | to_entries | .[0].value ) as $json_obj_value |
"\($text) | \($json_obj_value)"
' yourlogfile.log
Basically we
- Throw out any line without " | " in it
- Split each line into two parts
- Put the left part in a
$text
binding for legibility
- Parse the right part into json, get it's first value and put it in a
$json_obj_value
binding for legibility
- Print a string
"$text | $json_obj_value"
(\(foo)
is how you do interpolation on jq
)
If you want it as compact as possible, you can use
jq -Rr 'select(contains(" | "))|split(" | ")|"\(.[0]) | \(.[1]|fromjson|to_entries|.[0].value)"' yourlogfile.log
That will be smaller but also harder to read. Which is the best will depend on taste and use-case.