This is actually more interesting than it at first appears.
At least with GNU sed, it appears that $
is only treated as a regular expression metacharacter when it appears at the end of a pattern. So for example whereas:
$ echo 'config$' | sed 's/config$/foobar$/'
config$
needs to be
$ echo 'config$' | sed 's/config\$/foobar$/'
foobar$
the $
in
$ echo '$config' | sed 's/$config/$foobar/'
$foobar
works without escaping. However, because you've used weak (double) quotes around the sed expression to permit inclusion of literal single quotes, you need to escape the $
in $config
to prevent the shell expanding it (to a presumably empty value). Because it's the shell that's doing the expansion, it also needs to be escaped on the RHS of the replacement (where it wouldn't have been treated as a regex metacharacter).
On the other hand, [
(which is not special to the shell when double quoted) is treated as a regex metacharacter regardless of position, and needs to be escaped for that reason - while ]
doesn't need to be escaped when it isn't preceded by (unescaped) [
.
Finally, if the expansion of $2
may contain a forward slash (like the Asia/Jakarta
that it replaces), then that must also be escaped - or you must change the sed delimiter to a different character.
So given
$ cat config.php
$config['timezone'] = 'Asia/Jakarta';
$config['sess_cookie_name'] = 'sess_project';
and
var='North America/Chicago'
then
$ sed -e "/.*\$config\['timezone'] = .*/ s/.*/\$config['timezone'] = '${var//\//\\\/}';/" config.php
$config['timezone'] = 'North America/Chicago';
$config['sess_cookie_name'] = 'sess_project';
(note that I also corrected the presumed type *.
to .*
), or more simply
sed -e "/\$config\['timezone']/ s/=.*/= '${var//\//\\\/}';/" config.php
References:
- What characters do I need to escape when using sed in a sh script?
- Sed find and replace with slashes
*.
. Is this intentional or is it supposed to be.*
? – Kusalananda Oct 08 '20 at 14:40