0

I have a config. file for apache zookeeper which looks like this:

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/zookeeper/zkdata
clientPort=2184
server.1=10.1.1.191:2888:3888
server.2=10.1.1.70:2889:3889
server.3=10.1.1.71:2890:3890

I created a bash script that deletes the cfg file and replaces it with the exact same information except a different server.1=IP. This IP is variable and I need to change it very rarely. I want to know if there is a way to find the 10.1.1.191 and replace it with lets say 10.1.1.192 without doing:

rm zoo.cfg
echo "tickTime=2000" >> zoo.cfg
echo "initLimit=10" >> zoo.cfg
... (and so on till...)
echo "server.1=$1:2888:3888" >> zoo.cfg
echo "server.2=10.1.1.70:2889:3889" >> zoo.cfg
echo "server.2=10.1.1.71:2890:3890" >> zoo.cfg

This is my method right now. Delete zoo.cfg and replace with new ip for server.1.

Is there a way to find and replace the IP for server.1 in a bash script instead of deleting file?

  • 1
    Welcome to Stack Overflow! There are multiple ways to do this. Use can use either sed or awk. (I prefer awk). Take a peek at some tutorials and dive in. When you get stuck, ask a specific question, showing us what you've tried. – Leonard Aug 20 '18 at 18:49
  • `sed -i` seems a good candidate. – Poshi Aug 20 '18 at 18:50
  • @Leonard I will try awk also to see how it works! Thanks for the suggestion. – kpandey1337 Aug 20 '18 at 20:13

2 Answers2

1

You can do this with sed:

IP=10.1.1.192
sed -i "s/^server.1=.*\$/server.1=$IP:2888:3888/g" zoo.cfg
dbush
  • 205,898
  • 23
  • 218
  • 273
  • Thanks!! After deleting \$ and adding -e it worked. What is the .*\$ representing? I believe .* means the content after server.1=. what about \$? – kpandey1337 Aug 20 '18 at 19:23
  • @kpandey1337 The `$` represents the end of a line. The leading backslash is so the shell doesn't interpret it as denoting a variable name. – dbush Aug 20 '18 at 19:25
  • Thanks!! I see I'll keep the '$' in . Probably better. – kpandey1337 Aug 20 '18 at 19:27
0

Consider approaching a little differently in order to tighten up the regex matching and ensure you replace only the IP address and leave the rest of the line alone. Here, 3 "remembered" groups are created by surrounding the matches with parenthesis. The groups are then used by their numeric representation in the replace portion of the sed command.

This approach ensures a line starts with "server.1=" and is followed by an IP address, and whatever else follows is saved and does not have to be entered when updating the IP.

Regex explained:

^\(server\.1=\) - Group 1 is anchored to the beginning of the line and matches
                  the string "server.1=". Note the backslash takes
                  away special meaning.  The dot in reg means match any
                  character.  Here we need to match a dot itself.

\(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\) - Then, match an IP address.  4 numbers
                                         consisting of at least 1 but not more
                                         than 3 digits, separated by dots.
\(:.*?\)\$ - Group 3 is the rest of the line, starting with the colon and 
             anchored to the end of the line.

If all that is matched, replace with:

\1$IP\3 - remembered group 1, then the new IP address as stored in the 
          variable IP, then remembered group 3

Finally:

sed -i "s/^\(server\.1=\)\(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\)\(:.*?\)\$/\1$IP\3/g" zoo.cfg
Gary_W
  • 9,933
  • 1
  • 22
  • 40