Kinda cumbersome (as most Perl code, and by the moment I realized I was too invested to scrap the thing anyways), but it should be a fair attempt at parsing and modifying the right hand side of the option assignments as pseudo-JSONs in a proper manner, using Perl's JSON module (on Debian-based distros you could install the module via sudo apt install libjson-perl, or, of course, on any distro, you could install the module via CPAN).
The code is a bit terse at times, I'll just give a rough idea of what's going on.
perl -MJSON -pse '
BEGIN {$/ = "}"}
s
/^(([\n]+)?object = )(.*)
/$1 . to_json({ %{ from_json($3, {relaxed => 1}) }, split(\/:\/, $var) }, {pretty => 1})
/se
' <input -- -var='foo:bar'
Just the Perl code, formatted in a more human-readable manner, with syntax highlighting:
BEGIN {
$/ = "}"
}
s
/^(([\n]+)?object = )(.*)
/$1 . to_json(
{
%{ from_json($3, {relaxed => 1}) },
split(\/:\/, $var)
},
{pretty => 1}
)
/se
This will add a "foo":"bar" key / value pair to any valid JSON found on the right hand side of an option assignment found in the input file:
~ % cat input
object = {
"one": "one",
"two": "two",
}
object = {
"three": "three",
"four": "four",
}
~ % perl -MJSON -pse '
BEGIN {$/ = "}"}
s
/^(([\n]+)?object = )(.*)/
$1 . to_json({ %{ from_json($3, {relaxed => 1}) }, split(\/:\/, $var) }, {pretty => 1})
/se
' <input -- -var='foo:bar'
object = {
"one" : "one",
"two" : "two",
"foo" : "bar"
}
object = {
"four" : "four",
"three" : "three",
"foo" : "bar"
}
I won't break this down line by line, but the logic is:
- Read in a a string
foo:bar (which represents the key / value pair to add) and store it into a variable var
- Read the file using an input record separator of
}, so to split the file into multiple records delimited by the end of each JSON object
- If a record matches an optional sequence of newlines followed by
option = , treat the rest of the record as a valid "relaxed" JSON object (relaxed as in: commas are allowed after the last element of an object / array, which isn't strictly valid JSON)
- Deserialize the JSON string into a Perl hash, and add the key / value pair resulting from the splitting of
var on :
- Serialize the hash back into a JSON string, prettifying the output
Caveats:
- If a supplied key already exists in the pseudo-JSON object, its value will be overridden by the supplied value;
- The order of the key / value pairs in the input file won't necessarily be preserved;
- Likewise, the added key / value pair won't necessarily end up being the last in the list;
- Despite accepting pseudo-valid JSON objects as the JSON objects to process, this will output only valid JSON objects (i.e. the last key / value pair won't include a trailing comma)
jqinstead?