0

I am trying to replace a particular string in a file using the sed command. However, it is not working. Structure of data in my file:

"SomeServerName": {
    "serverIP": "192.168.0.132",
    "serverPort": "9999",
    "active": false
}

In this, I want to change active status to true from false on the basis of IP which is a variable input I get from the terminal.

The sed command I have used is :

sudo sed -i "s/$someIP/!b;n;n;c\ \ \ \ \ \ \ \ "active": true/" filename

Here, $someIP=192.168.0.132. In sed, if I replace $someIP with '192.168.0.132' it works fine. However, if I pass the variable, it does not work.

EDIT: Below is my whole script for the above sed:

#! /bin/sh

someIP=$(hostname -I)
sudo sed -i "s/$someIP/!b;n;n;c\ \ \ \ \ \ \ \ "active": true/" filename
11
  • are you executing the command from script or commandline? where is someIP set? i am having trouble reproducing this behavior. Commented Sep 7, 2018 at 17:06
  • I am executing this from a script. I get the someIP by running the command hostname -I and then assigning it to the variable someIP Commented Sep 7, 2018 at 17:08
  • I am sorry. I have edited the sed command to exactly my requirement. Commented Sep 7, 2018 at 17:13
  • might want to try putting your $someIP into ${someIP} but im not postive on that Commented Sep 7, 2018 at 17:14
  • 1
    You should use a JSON parser such as jq for this, not sed. Commented Sep 7, 2018 at 17:20

2 Answers 2

1

how about

sed -zE "s/($someIP[^\n]*\n[^\n]*\n[^\n]*\"active\": )false/\1true/g" filename

you can not literally "pass" a variable to sed. bash replaces $someIP in the argument with the string it refers to before it starts sed, i.e. it's a pass by value.

beware that $someIP does not just match 192.168.0.132 though, but also 192:168:0:132 or 1924168903132 because to sed '.' means "any character", if you don't escape it.

this command will work as long as the matched IP and the "active" setting have exactly two lines and otherwise unspecified content between them.

Sign up to request clarification or add additional context in comments.

4 Comments

This treats the whole input as a single line and will change false to true everywhere. I assume the real input has more than one JSON object in it.
with the g flag it should, as long as every entry has this same basic structure. if things are more complex, i will agree with you that sed is simply the wrong tool.
The point is that since the whole file is treated as a single line, your command will turn it to true everywhere, but you'd want it just for the entry right after the IP address match.
it makes one replacement for each match found. but you are right, there is one major concern. if active was already set for one IP block the next block with active set to false would be affected. will fix.
1

Here is a sed solution. Note, you need to use double-quotes "" for sed and escape any other double quotes in the search or replace strings.

 $ input_ip="192.168.0.132"
 $ sed -i "/$input_ip/{n;n;s/\"active\": false/\"active\": true/}" inputFile

This assumes, active: false string appears two lines after the $input_ip. n;n; skips two lines at the end of $input_ip.

Comments

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.