-1

i do have a JSON file as below:-

{
  "Rules": [
    {
      "ID": "DMS-FULL-HISTORY-DATA-DEEPARCHIVE-1d",
      "Filter": {
        "Prefix": "HISTORY/DATA/"
      },
      "Status": "Enabled",
      "Transitions": [
        {
          "Days": 1,
          "StorageClass": "DEEP_ARCHIVE"
        }
      ]
    },
    {
      "ID": "FOL-FULL-HISTORY-DATA-DEEPARCHIVE-1d",
      "Filter": {
        "Prefix": "HISTORY/DATA/"
      },
      "Status": "Enabled",
      "Transitions": [
        {
          "Days": 1,
          "StorageClass": "DEEP_ARCHIVE"
        }
      ]
    },
    {
      "ID": "Hello-CDC-delete-30d",
      "Filter": {
        "Prefix": "CDC/"
      },
      "Status": "Enabled",
      "Expiration": {
        "Days": 30
      }
    }
  ]
}

I want to only lookout for the rule IDs containing '-FULL-HISTORY-DATA' and then updating its Status to "Disabled". Rest file remains unchanged. Is there a way to do edit without opening the file using single shell command or sed?

Desired output:-

{
  "Rules": [
    {
      "ID": "DMS-FULL-HISTORY-DATA-DEEPARCHIVE-1d",
      "Filter": {
        "Prefix": "HISTORY/DATA/"
      },
      "Status": "Disabled",
      "Transitions": [
        {
          "Days": 1,
          "StorageClass": "DEEP_ARCHIVE"
        }
      ]
    },
    {
      "ID": "FOL-FULL-HISTORY-DATA-DEEPARCHIVE-1d",
      "Filter": {
        "Prefix": "HISTORY/DATA/"
      },
      "Status": "Disabled",
      "Transitions": [
        {
          "Days": 1,
          "StorageClass": "DEEP_ARCHIVE"
        }
      ]
    },
    {
      "ID": "Hello-CDC-delete-30d",
      "Filter": {
        "Prefix": "CDC/"
      },
      "Status": "Enabled",
      "Expiration": {
        "Days": 30
      }
    }
  ]
}

I have tried using sed , but that is performing update to all rule ids.

cfrick
  • 35,203
  • 6
  • 56
  • 68
Zack_Coder
  • 51
  • 4
  • Please add to your question (no comment): What have you searched for, and what did you find? What have you tried, and how did it fail? – Cyrus Nov 01 '21 at 10:24
  • 1
    Given your context, it looks like using a JSON parser from your `bash` environment would help a lot. You might appreciate `jq` ([homepage](https://stedolan.github.io/jq/), [manual](https://stedolan.github.io/jq/manual/), SO tag : [tag:jq]) – Aaron Nov 01 '21 at 10:25
  • you won't be able to post a full JSON document in the comments, the previous commenter wanted you to edit your question to include the desired output. It helps getting correct answers, although your question is pretty clear as far as I can tell – Aaron Nov 01 '21 at 10:28
  • updated question. Also cant use JSON parser, as this is being accomplished in groovy env. – Zack_Coder Nov 01 '21 at 10:30
  • or: [Perl has several JSON parsers available and since Perl 5.14](https://stackoverflow.com/a/62344545/3776858). – Cyrus Nov 01 '21 at 10:37
  • 2
    or: [How to modify JSON in groovy](https://stackoverflow.com/q/20104819/3776858) – Cyrus Nov 01 '21 at 10:41
  • 2
    I think assuming you can't use a JSON parser from your groovy env is a mistake. Java has JSON parsers so Groovy does too, and if you're able to run bash commands as the tags you used seem to suggest then you can run `jq` (although making sure it's installed on the target bash env is another question). Anyway providing a sed-based answer that doesn't need to be as robust as a JSON-parser based answer would be is easy, so I'll work on that – Aaron Nov 01 '21 at 10:44
  • 1
    JSON parsing is even built-in Groovy/Gradle. It would be really counter-productive to call a bash script to modify a JSON file in the context of a Gradle build script for example. – Léa Gris Nov 01 '21 at 10:56
  • Could you please relate why the programming lanugage Groovy is relevant here? Is this for jenkins? – cfrick Nov 01 '21 at 11:16
  • @cfrick yes...!! – Zack_Coder Nov 01 '21 at 11:27

2 Answers2

1

If you really want a sed command, you can use the following :

sed '/.*FULL-HISTORY-DATA.*/{N;N;N;N;s/"Status": "Enabled"/"Status": "Disabled"/}'

You can try it here.

Every time sed encounters a line that contains 'FULL-HISTORY-DATA', it consumes the next 4 lines of data and replace "Status": "Enabled" by "Status": "Disabled" in them.

This is a very fragile process as any unsignificant change in JSON formatting might make it fail, as will having two occurences of FULL-HISTORY-DATA in less than 4 lines (the second will be consumed when the first is handled and won't be properly processed by the command).

If you need something reliable and robust you will want to use a JSON parser.

Aaron
  • 24,009
  • 2
  • 33
  • 57
  • OK...then how to go with jq? – Zack_Coder Nov 01 '21 at 10:59
  • I've added a jq-based answer. If `jq` is not installed on your jenkins hosts, it might be better to use the JSON parser included in groovy that @léa-gris mentions though. – Aaron Nov 01 '21 at 12:01
1

If the jq command-line JSON parser is available, you can use the following command :

jq '.Rules |= map((select(.ID | contains("FULL-HISTORY-DATA"))| .Status = "Disabled" ) // .)'

You can try it online.

Aaron
  • 24,009
  • 2
  • 33
  • 57