1

I am using sed for string replacement in a config file.

User has to input the string salt and then I replace this salt string in the config file:

Sample config file myconfig.conf

CONFIG_SALT_VALUE=SOME_DUMMY_VALUE

I use the command to replace dummy value with value of salt entered by the user.

sed -i s/^CONFIG_SALT_VALUE.*/CONFIG_SALT_VALUE=$salt/g" ./myconfig.conf

Issue : value of $salt can contain any character, so if $salt contains / (like 12d/dfs) then my above sed command breaks.

I can change delimiter to !, but now again if $salt contains amgh!fhf then my sed command will break.

How should I proceed to this problem?

chrisaycock
  • 36,470
  • 14
  • 88
  • 125
voila
  • 1,594
  • 2
  • 19
  • 38

1 Answers1

1

You can use almost any character as sed delimiter. However, as you mention in your question, to keep changing it is fragile.

Maybe it is useful to use awk instead, doing a little bit of parsing of the line:

awk 'BEGIN{repl=ARGV[1]; ARGV[1]=""; FS=OFS="="}
     $1 == "CONFIG_SALT_VALUE" {$2=repl}
     1' "$salt" file

As one liner:

awk 'BEGIN{repl=ARGV[1]; ARGV[1]=""; FS=OFS="="} $1 == "CONFIG_SALT_VALUE" {$2=repl}1' "$salt" file

This sets = as field separator. Then, it checks when a line contains CONFIG_SALT_VALUE as parameter name. When this happens, it replaces the value to the one given.

To prevent values in $salt like foo\\bar from being interpreted, as that other guy commented in my original answer, we have the trick:

awk 'BEGIN{repl=ARGV[1]; ARGV[1]=""} ...' "$var" file

This uses the answer in How to use variable including special symbol in awk? where Ed Morton says that

The way to pass a shell variable to awk without backslashes being interpreted is to pass it in the arg list instead of populating an awk variable outside of the script.

and then

You need to set ARGV[1]="" after populating the awk variable to avoid the shell variable value also being treated as a file name. Unlike any other way of passing in a variable, ALL characters used in a variable this way are treated literally with no "special" meaning.

This does not do in-place editing, but you can redirect to another file and then replace the original:

awk '...' file > tmp_file && mv tmp_file file
Community
  • 1
  • 1
fedorqui
  • 275,237
  • 103
  • 548
  • 598