1

I'm trying to replace some text in a file as described in title. What i tried:

newdir=/dir/to/my/file
sed -i "s/'MyDir'/${newdir}/g" myconf.conf

The command above gives this error:

unknown option to `s'

Toto
  • 89,455
  • 62
  • 89
  • 125
postgresnewbie
  • 1,378
  • 1
  • 12
  • 19

2 Answers2

4

The problem is that $newdir contains / characters, so your sed command ends up looking like s/'MyDir'//dir/to/my/file/g, which won't work -- the first / effectively terminates your sed expression, and everything else is garbage.

Fortunately, sed let's you use any character as a delimiter to the s command, so you could write instead:

sed -i "s|'MyDir'|${newdir}|g" myconf.conf
larsks
  • 277,717
  • 41
  • 399
  • 399
  • Though unfortunately, a path can contain any other character that you might use as the delimiter. You always have to be aware of the contents of `newdir`, as you aren't passing a parameter to `sed`: you are building a `sed` script dynamically. – chepner Jul 28 '21 at 13:54
3

One way to get around the "does my data contain the delimiter" problem is to use shell variable expansion to escape the delimiter character:

sed -i "s|'MyDir'|${newdir//|/\\|}|g" myconf.conf

Demo:

$ newdir="/a/dir/with|a/pipe"

$ sed "s|'MyDir'|${newdir}|g" <<< "this is 'MyDir' here"
sed: 1: "s|'MyDir'|/a/dir/with|a ...": bad flag in substitute command: 'a'

$ sed "s|'MyDir'|${newdir//|/\\|}|g" <<< "this is 'MyDir' here"
this is /a/dir/with|a/pipe here

You can do this with the default slash delimiter, with more escapes

sed -i "s/'MyDir'/${newdir//\//\\\/}/g" myconf.conf
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • Escaping the delimiter is a good start. However, there may be more symbols which need escaping, for example `&` and `\ ` (especially when it is trailing). – Socowi Jul 28 '21 at 19:53