The expression in your configuration file looks like a PHP code, and the value for database is most likely an URI.
SED
According to RFC 3986 the special characters must be percent-encoded within URI parts. Let's use #
character as a delimiter for SED substitution, as the character must be percent-encoded everywhere, except the fragment marker which will not be used in your URI, obviously.
Let's assume that the assignment is not distributed on multiple lines. Then you can run the following command to replace the old $database
variable with new value:
# If you want to automate escaping, use rawurlencode() function, for example:
user=$(php -r 'echo rawurlencode($argv[1]);' 'user&#')
pass=$(php -r 'echo rawurlencode($argv[1]);' 'pass@ ')
# Make sure to escape sed-specific characters within the string, as it will be
# embedded into sed script below! Note, we use `#` as a delimiter for substitution.
database="'mysql://${user}:${pass}@localhost/new_database'"
sed -i.bak -e 's#^\([[:space:]]*\$database[[:space:]]*=\).*;#\1 '"$database"';#' \
config.php
# With GNU sed
sed -i.bak -r 's#^(\s*\$database\s*=).*;#\1 '"$database"';#' config.php
Input
$database = 'mysql://custom_user:custom_password@localhost/custom_database';
$database = "mysql://custom_user:Pass&word@localhost/custom_database" ;
$database = "mysql://custom_user:Pass&word@localhost" . "/custom_" . "database" ;
Output
$database = 'mysql://user%26%23:pass%40%20@localhost/new_database';
$database = 'mysql://user%26%23:pass%40%20@localhost/new_database';
$database = 'mysql://user%26%23:pass%40%20@localhost/new_database';
Perl
script.pl
use strict;
use warnings;
my ($u, $p, $h, $d) = (shift, shift, shift, shift);
while (<>) {
my $uri = sprintf("'mysql://%s:%s@%s/%s'",
uri_escape($u),
uri_escape($p),
$h, $d);
s/^(\s*\$database\s*=).*;/"$1 ${uri};"/eg;
print;
}
Usage
perl -i.bak -MURI::Escape script.pl \
'user&#' 'pass@ ' 'localhost' 'new_database' config.php
PHP
If my guess is right, and you are running PHP, then consider using two configuration files:
- in the code repository,
conf.php
,
- server-local,
conf2.php
:
The simplest implementation in PHP might look like the following.
conf.php
<?php
return [
'db' => [
'user' => 'default user',
'host' => 'default host',
],
];
conf2.php
<?php
$default = require('conf.php');
return array_replace_recursive($default, [
'db' => [
'user' => 'local user',
'host' => 'local host',
],
]);
test.php
<?php
$conf = require('conf2.php');
var_dump($conf);
Testing:
php test.php
Output
array(1) {
["db"]=>
array(2) {
["user"]=>
string(10) "local user"
["host"]=>
string(10) "local host"
}
}