使用jq查找并替换文件中的json

时间:2021-06-17 16:49:21

I am new at using jq and could use help with the following...

我是使用jq的新手,可以使用以下帮助......

In essence, I am trying to "find and replace" a block of json in a file using a bash script.

本质上,我试图使用bash脚本在文件中“查找并替换”一个json块。

I have a file called docs.json to where I retrieved a set of doc entries:

我有一个名为docs.json的文件,我在其中检索了一组doc条目:

{
    "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":

而我正在尝试用一个存储在名为“doc”的变量中的新json块替换所有具有“_attachments”的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?

我正在尝试使用jq并在bash脚本中运行吗?

Thank you for the help and tips, in advance.

感谢您的帮助和提示,提前。

2 个解决方案

#1


2  

The key is to select the documents that have the _attachments key, then replace them with the |= operator.

关键是选择具有_attachments键的文档,然后用| =运算符替换它们。

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.

--argjson用于将$ doc的值作为原始JSON值传递给过滤器。

#2


0  

If you cannot use --argjson you could use the -s slurp option along with a filter such as

如果你不能使用--argjson,你可以使用-s slurp选项和一个过滤器,如

  .[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

如果以上是在filter.jq中,你在new.json中的新文档和你的数据包含你在docs.json中描述的单个对象然后

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

注意 - 我没有jq-1.3所以我只能用jq-1.5验证这个,但我相信这应该适用于jq-1.3

#1


2  

The key is to select the documents that have the _attachments key, then replace them with the |= operator.

关键是选择具有_attachments键的文档,然后用| =运算符替换它们。

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.

--argjson用于将$ doc的值作为原始JSON值传递给过滤器。

#2


0  

If you cannot use --argjson you could use the -s slurp option along with a filter such as

如果你不能使用--argjson,你可以使用-s slurp选项和一个过滤器,如

  .[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

如果以上是在filter.jq中,你在new.json中的新文档和你的数据包含你在docs.json中描述的单个对象然后

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

注意 - 我没有jq-1.3所以我只能用jq-1.5验证这个,但我相信这应该适用于jq-1.3