我有两个 php 文件将被 sed 替换
第一个是
$db['default'] = array(
'dsn' => '',
'hostname' => 'localhost',
'username' => 'demo',
'password' => 'demopass',
'database' => 'dbname'
);
我需要将 dbname 从 shell 脚本替换为动态变量 我使用这个脚本并工作
sed -i -e "/.*'database' =>*./ s/.*/'database' => '$1',/" /var/www/project/application/config/database.php
第二个文件是
$config['timezone'] = 'Asia/Jakarta';
$config['sess_cookie_name'] = 'sess_project';
我需要将“亚洲/雅加达”更改为另一个动态变量,但它不起作用,因为它开头有 $ 符号。这是我的代码
sed -i -e "/.*$config['timezone'] = *./ s/.*/$config['timezone'] = '$2';/" /var/www/project/application/config/config.php
谢谢
答案1
这实际上比乍一看更有趣。
至少对于 GNU sed,看起来$
只有当它出现在模式末尾时才被视为正则表达式元字符。例如:
$ echo 'config$' | sed 's/config$/foobar$/'
config$
需要是
$ echo 'config$' | sed 's/config\$/foobar$/'
foobar$
在$
$ echo '$config' | sed 's/$config/$foobar/'
$foobar
无需逃避即可工作。然而,因为您在 sed 表达式周围使用了弱(双)引号以允许包含文字单引号,所以您需要转义$
in$config
以防止壳将其扩展(大概为空值)。因为是 shell 进行扩展,所以它还需要在替换的 RHS 上进行转义(它不会被视为正则表达式元字符)。
另一方面,[
(即不是双引号时对 shell 来说是特殊的)是无论位置如何,都被视为正则表达式元字符,因此需要转义 - while]
当前面没有 (unescaped) 时不需要转义[
。
最后,如果 的扩展$2
可能包含正斜杠(如它所Asia/Jakarta
替换的),那么也必须对其进行转义 - 或者您必须将 sed 分隔符更改为其他字符。
所以给出
$ cat config.php
$config['timezone'] = 'Asia/Jakarta';
$config['sess_cookie_name'] = 'sess_project';
和
var='North America/Chicago'
然后
$ sed -e "/.*\$config\['timezone'] = .*/ s/.*/\$config['timezone'] = '${var//\//\\\/}';/" config.php
$config['timezone'] = 'North America/Chicago';
$config['sess_cookie_name'] = 'sess_project';
(请注意,我还将假定类型更正*.
为.*
),或更简单地说
sed -e "/\$config\['timezone']/ s/=.*/= '${var//\//\\\/}';/" config.php
参考:
答案2
你的 sed 似乎过于复杂。我建议(假设这个脚本被称为t
):
!/bin/bash
sed -i -e "s~\$config['timezone']\s*=\s*'.*';~\$config['timezone'] = '$1';~i" /var/www/project/application/config/config.php
并像这样调用它:./t 'Asia/Novokuznetsk'
。请注意,由于正则表达式分隔符,斜杠不会被转义~
。美元符号被转义,除了$1
.
答案3
repl_rhs=$(printf '%s\n' "$1" | sed -e 's:[\&/'\'']:\\&:g')
sed -e "
/\(\$config[[]'timezone'] =\).*/s//\1 '$repl_rhs'/
" file.php
- 转义 rhs 元字符 + s/// 分隔符 + php 单引号字符串
- 替换字符串 $1 中没有换行符