Reputation: 15
I am new at using jq and could use help with the following...
In essence, I am trying to "find and replace" a block of json in a file using a bash script.
I have a file called docs.json to where I retrieved a set of doc entries:
{
"number_of_docs": "1000",
"docs": [{
{
"_id": "000001",
"_rev": "0",
"_content": "abcdefg"
},
{
"_id": "000002",
"_rev": "0",
"_content": "hijklmn",
"_attachments": {
"image1.png": {
"content_type": "image/png"
...
}
}
},
{
"_id": "000003",
"_rev": "0",
"_content": "opqrstuv"
}]
}
And I'm trying to replace all the doc entries (the entire block, not just the value of the keys) that have "_attachments" with a new block of json that is stored in a variable named "doc":
{
"_id": "000002_masked",
"_rev": "0",
"_content": "[Document content has been masked for confidentiality.]",
"_attachments": {
"confidential.png": {
"content_type": "image/png"
...
}
}
}
Is what I'm trying to do possible with jq and running from within a bash script?
Thank you for the help and tips, in advance.
Upvotes: 0
Views: 3649
Reputation: 14725
If you cannot use --argjson
you could use the -s
slurp option along with a filter such as
.[0] as $new
| .[1]
| ( .docs[] | select(has("_attachments")) ) = $new
if the above is in filter.jq
, your new document in new.json
and your data contains a single object as you describe in docs.json
then
jq -M -s -f filter.jq new.json docs.json
will produce
{
"number_of_docs": "1000",
"docs": [
{
"_id": "000001",
"_rev": "0",
"_content": "abcdefg"
},
{
"_id": "000002_masked",
"_rev": "0",
"_content": "[Document content has been masked for confidentiality.]",
"_attachments": {
"confidential.png": {
"content_type": "image/png"
}
}
},
{
"_id": "000003",
"_rev": "0",
"_content": "opqrstuv"
}
]
}
Note - I don't have jq-1.3 so I'm only able to verify this with jq-1.5 but I believe this should work with jq-1.3
Upvotes: 0
Reputation: 532418
The key is to select the documents that have the _attachments
key, then replace them with the |=
operator.
jq --argjson new "$doc" '(.docs[]| select(has("_attachments"))) |= $new' docs.json
--argjson
is used to pass the value of $doc
into the filter as a raw JSON value.
Upvotes: 3