0

I work with Json looks something like below

[
    {
      "accessType": "*",
      "principalType": "ROLE",
      "principalId": "$unauthenticated",
      "permission": "DENY"
    },
    {
      "accessType": "*",
      "principalType": "ROLE",
      "principalId": "everyone",
      "permission": "Allow"
    },
    {
      "accessType": "*",
      "principalType": "ROLE",
      "principalId": "$owner",
      "permission": "ALLOW"
    }
  ]

I would like to change the access type to "restricted" instead of "*" for the PrincipalID: "everyone"... I am using something like sed '\{[^}]*?everyone[^}]*\},s,"accessType": "*","accessType": "Restricted",' sdcard/etc/sample.json but it doesnt work. it has to look like below:

{
      "accessType": "Restricted",
      "principalType": "ROLE",
      "principalId": "everyone",
      "permission": "Allow"
    },

it is a continuation to the previous question: Regex to match specific, multiline object in JSON list

I cannot use any 3rd party applications to perform this action, only using sed and regex or any 1 liner unix command

1
  • 4
    You should generally not try to use regex to parse JSON. Use the right tool for the job (probably not Sed). Use a JSON parser. Commented Nov 2, 2020 at 15:55

3 Answers 3

1

sed is not the right tool for the job. Use jq, a JSON-aware tool that can parse JSON even if its formatting changes.

jq '.[] |= (if .principalId == "everyone"
            then (.accessType |= "restricted")
            else . end)' \
    file.json
Sign up to request clarification or add additional context in comments.

Comments

1

You can use a JSON parser for this, like jq.

I put your json in a file (called jsonfile below) and can obtain your desired result like

$ cat jsonfile | jq. '.[0]'.   // OR jq '.[0]' jsonfile
{
  "accessType": "*",
  "principalType": "ROLE",
  "principalId": "everyone",
  "permission": "Allow"
}
// also works for .[1] and .[2]

Now I adjust the right json field like this:

$ jq '.[].accessType = "Restricted"' jsonfile
[
  {
    "accessType": "Restricted",
    "principalType": "ROLE",
    "principalId": "$unauthenticated",
    "permission": "DENY"
  },
  {
    "accessType": "Restricted",
    "principalType": "ROLE",
    "principalId": "everyone",
    "permission": "Allow"
  },
  {
    "accessType": "Restricted",
    "principalType": "ROLE",
    "principalId": "$owner",
    "permission": "ALLOW"
  }
]

and I can grep the first JSON list with a pipe:

$ jq '.[].accessType = "Restricted"' jsonfile | jq '.[0]'
{
  "accessType": "Restricted",
  "principalType": "ROLE",
  "principalId": "$unauthenticated",
  "permission": "DENY"
}

1 Comment

A small improvement would be to use one jq command (which I think should be possible), but jq '.[0] | fromjson | .[].accessType = "Restricted"' jsonfile' gives an error that only strings can be parsed... Working on it
-1

Assuming you are sticking to this basic and known JSON structure and assuming SED supports a lot of PCRE syntax then this would work:

(\{[^}]+"accessType": ")(\*)(",[^}]+"principalId": "everyone",[^}]+\})

https://regex101.com/r/xt6DY9/1/

1 Comment

This pattern is POSIX ERE compliant, but that means OP must know how to enable it and how to properly quote the sed command.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.