0

I am trying to replace the following string with another one from a file which contains few lines.

"schema" : "AAAAA",

TO

"schema" : "BBBBB",

Currently, I am doing the following command to get the corresponding line with "schema"

currentSchema=cat test.json | grep schema | awk {'print $3'}

It will give me the value "AAAAA",

I would like to replace AAAAA with BBBBB

I used the following command

sed -e 's/$currentSchema/BBBBB/p' test.json

However, it is not able to replace in the same file.

  • 1
    Add an -i switch to the sed command to edit the file in place. – doneal24 Oct 16 '18 at 17:31
  • 2
    Consider using jq instead to perform operations on JSON files. It's a better tool, since it understands the actual underlying format, so it's able to do a better job on it than awk and sed. – filbranden Oct 16 '18 at 17:41
  • really? how jq can replace the strings? – user3613331 Oct 16 '18 at 18:03
  • 1
    $currentSchema does not expand within strong/single quotes. – fd0 Oct 16 '18 at 19:03
4

Example JSON file:

[
  {
    "host": "myhost",
    "schema": "AAAAA",
    "lunch": "sandwich"
  },
  {
    "host": "myotherhost",
    "schema": "QQQQQ",
    "lunch": "pizza"
  }
]

We'd like to replace each schema that is AAAAA with BBBBB. We can do this with jq:

$ jq 'map(if .schema == "AAAAA" then .schema = "BBBBB" else . end)' file.json
[
  {
    "host": "myhost",
    "schema": "BBBBB",
    "lunch": "sandwhich"
  },
  {
    "host": "myotherhost",
    "schema": "QQQQQ",
    "lunch": "pizza"
  }
]

If it doesn't matter what the old schema was:

$ jq 'map(.schema = "BBBBB")' file.json
[
  {
    "host": "myhost",
    "schema": "BBBBB",
    "lunch": "sandwhich"
  },
  {
    "host": "myotherhost",
    "schema": "BBBBB",
    "lunch": "pizza"
  }
]

Since jq is a proper JSON parser, this would work even if the file was presented in a more compact form, for example as the single line

[{"host":"myhost","schema":"AAAAA","lunch":"sandwhich"},{"host":"myotherhost","schema":"QQQQQ","lunch":"pizza"}]

For the actual problem (in comments), which is to find the element in .rules.behavior[] that has a .name key with value mPulse and then to change that element's .options.apiKey to some other value:

jq '.rules.behaviors = [.rules.behaviors[]|select(.name == "mPulse").options.apiKey = "XXX"]' file.json

That is, rewrite the .rules.behaviour array in such a way that the element whose .name key is mPulse gets a new .options.apiKey.

1

A couple of optimizations, not least of which is eschewing a "useless use of cat". You don't need to cat file | grep pattern; you can just grep pattern file. And since you're grepping into awk, that can be simplified too:

currentSchema="$( cat test.json | grep schema | awk '{print $3}' )"

becomes

currentSchema="$( awk '/schema/ {print $3}' test.json )"

Now, for your sed script. You are using Strong Quotes (') around your sed command, which means your shell variables will not be parsed. You need to use Weak Quotes (") for this to work:

currentSchema="$( awk '/schema/ {print $3}' test.json )"
sed --in-place "s/$currentSchema/BBBBB/" test.json
  • Thanks for the optimization steps! I tried the second command but it is giving the following error sed --in-place "s/$currentSchema/BBBBB" rex.json – user3613331 Oct 16 '18 at 17:47
  • sed: -e expression #1, char 40: unterminated `s' command – user3613331 Oct 16 '18 at 17:48
  • You need a final / after the replacement. s/new/old/. – DopeGhoti Oct 16 '18 at 17:49
  • rex.json contains "schema" : "AAAAA-AAAAA-AAAAA-AAAAA-AAAAA", currentSchema="$( awk '/schema/ {print $3}' rex.json )" sed --in-place 's/$currentSchema/BBBBB-BBBBB-BBBBB-BBBBB-BBBBB/' rex.json But nothing has been changed in rex.json file – user3613331 Oct 16 '18 at 17:58
0

You don't need grep, awk, and sed for this; awk can do all the task (untested):

awk '/schema/ {$3 = "BBBBB"} 1' test.json > /tmp/$$ && mv /tmp/$$ test.json

Please try and report back.

  • 1
    That will change the entire .json file to only the newly-changed line, discarding the rest of the contents. – DopeGhoti Oct 16 '18 at 17:30
  • @DopeGhoti: Not sure I understand? – RudiC Oct 16 '18 at 17:32
  • awk '/schema/ {$3 = "BBBBB"} 1' rex.json > /tmp/$$ && mv /tmp/$$ yy.json But yy.json contains the same AAAAA itself.. did not change. Where rex.json contains "AAAAA-AAAAA-AAAAA-AAAAA-AAAAA", – user3613331 Oct 16 '18 at 17:33
  • oops... please excuse.. let me update the contents in rex.json – user3613331 Oct 16 '18 at 17:35
  • currently, rex.json contains "schema" : "AAAAA-AAAAA-AAAAA-AAAAA-AAAAA", I tried the following command awk '/schema/ {$3 = "BBBBB"} 1' rex.json > /tmp/$$ && mv /tmp/$$ yy.json Now yy.json has "schema" : BBBBB Almost there... I need to keep double-quotes there itself along with comma. Basically the entire line should be same. – user3613331 Oct 16 '18 at 17:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.