'Replace same occurrence of word with different words using sed

I want to replace 2 same words in file(app.properties) with 2 different words using sed command. Example:

mysql.host=<<CHANGE_ME>>
mysql.username=testuser
mysql.port=3306
mysql.db.password=<<CHANGE_ME>>

required output will be

mysql.host=localhost
mysql.username=testuser
mysql.port=3306
mysql.db.password=password123

I tried below command:

sed -e "s/<<CHANGE_ME>>/localhost/1" -e "s/<<CHANGE_ME>>/password123/2" app.properties > /home/centos/SCRIPT/io.properties_new

However I am getting localhost at both the places.



Solution 1:[1]

I'm sure it's not impossible, but also that you will not be able to figure out how it works once you find an answer. A better solution is to switch to a language which is more human-readable, so you can understand what it does.

awk 'BEGIN { split("localhost:password123", items, ":") }
    /<<CHANGE_ME>>/ { sub(/<<CHANGE_ME>>/, items[++i]) } 1' input_file >output_file

The BEGIN block creates an array items of replacements. The main script then increments i every time we perform a replacement, indexing further into items for the replacement string.

Solution 2:[2]

This may be possible but I don't know if this is really readable for everyone. Something like this might suite you :

sed -e '0,/<<CHANGE_ME>>/{s/<<CHANGE_ME>>/localhost/}' -e '1,/<<CHANGE_ME>>/{s/<<CHANGE_ME>>/password123/}' app.properties > /home/centos/SCRIPT/io.properties_new

If you have any idea to improve this, don't hesitate. I would really like to learn the best way to do this too :D

Solution 3:[3]

Using sed

$ sed '/host/s/\(=\).*/\1localhost/;/password/s/\(=\).*/\1password123/' input_file
mysql.host=localhost
mysql.username=testuser
mysql.port=3306
mysql.db.password=password123

Solution 4:[4]

With sed, using a wonderfully confusing if (first time) do x, else do y logic:

sed '/<CHANGE_ME>/{bb;:a;s/<CHANGE_ME>/password123/;:b;x;s/E//;x;ta;s/<CHANGE_ME>/localhost/;x;s/^/E/;x}' input_file

Writing each command of the sed script on its own line makes it more understandable, or at least easier for me to expain it:

/<CHANGE_ME>/{
  bb
  :a
  s/<CHANGE_ME>/password123/
  :b
  x
  s/E//
  x
  ta
  s/<CHANGE_ME>/localhost/
  x
  s/^/E/
  x
}

Here's the explanation:

  • /<CHANGE_ME>/{…} means that the stuff in {…} is only applied to lines matching <CHANGE_ME>;
  1. bb: "branch to (go to) :b", in this case used to skip the first substitution command;
  2. :a: a target for another branch or test-and-branch command;
  3. s/…/…/: you know what it does, but we skip this the first time the script is run;
  4. b: branches to the end of the script, skipping everything (because we are giving no argument to b);
  5. :b: the target of the command bb at 1.;
  6. x: swap patter space (the line you're dealing with at the moment), with the hold space (a kind of variable that you can put stuff into via x, h, and H commands);
  7. s/E//: tries to match and delete a E (just because that's the initial of my name), which fails the first time we run this, because the hold space that we've swapped earlier with the patter space was empty;
  8. x: undos what the previous x did, so we're back on working with the line matching <CHANGE_ME>;
  9. ta: tests if last peformed s/…/…/ command succeeded and, if so, it goes to :a, otherwise it's a no-op; the first time we run the script this is a no-op, because step 6 failed;
  10. s/…/…/: you know what it does;
  11. x: see above
  12. s/^/E/: inserts the E at the beginning of the line, so that next time we run the script substitution of step 7 succeedes, step 9 successfully branches to :a, step 3 is peformed for the first time, and step 4 exits the script for ever;
  13. x: see above

Solution 5:[5]

Perhaps this might help:

sed -e '1s/<<CHANGE_ME>>/localhost/' \
    -e '4s/<<CHANGE_ME>>/password123/' \
      app.properties > /home/centos/SCRIPT/io.properties_new

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 tripleee
Solution 2 Kayneth
Solution 3 HatLess
Solution 4
Solution 5 tripleee