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