使用 bash 脚本替换多个文件中的密码时转义特殊字符
Escape special characters when replacing passwords in multiple files with a bash-script
我发现了很多封闭的问题,但并不完全适合我的用例,因此不得不打开一个新问题。
猜猜一个系统的密码由多个配置文件中的所有大小写字母、数字和特殊字符(a-z、A-Z、0-9、#)组成(Web 应用程序使用相同的密码)在主域、子域和所有相关数据库上)。带有密码的此类文件的示例为:
$databases = array (
'default' =>
array (
'default' =>
array (
'database' => 'database_name',
'username' => 'datbase_user',
'password' => 'yv[48k2)KMGx{g1b',
'host' => 'localhost',
'port' => '',
'driver' => 'mysql',
'collation' => 'utf8mb4_general_ci',
'charset' => 'utf8mb4',
'prefix' => '',
),
),
);
我正在尝试编写一个 bash 代码,它接受自动生成的新密码(使用相同的算法 - 所有小写和大写字母、数字和特殊字符),找到所有出现的旧密码在各自父域及其子域的主目录中,并替换为新密码。以下单行工作正常:
grep -rlF "$old_pass" /path/to/directory | xargs sed -i "s/$old_pass/$new_pass/g"
对于仅由字母和数字组成的密码(例如 qVYYgB5bRxUYpHg
)。然而,虽然 grep
部分工作正常,但 sed
部分一旦系统将特殊字符添加到生成的密码(例如 aN#zDU>lve15Uwqn
)给出:
sed -i "s/$old_pass/$new_pass/g" password.php
sed: -e expression #1, char 37: unterminated `s' command
替换所有现有密码的最佳方法是什么,该密码由多个文件中不同变量中存储的所有字母、数字和特殊字符组成?
你的 sed 表达式是错误的,因为你需要转义方括号 [
:
sed -i 's/yv\[48k2)KMGx{g1b/aN#zDU>lve15Uwqn/g' password.php
为避免 shell 参数扩展,请在 sed
表达式中使用单引号。
如果要匹配所有字母、数字和特殊字符(假设标点符号),可以使用class个字符:
sed 's/[[:punct:][:alnum:]]*/NEWPASSWORKD/g' password.php
我认为自动生成的密码的可能排列可能超出了您将能够轻松适应 sed
的范围,但问题的症结在于保护元字符。对于这个具体的例子:
$: echo "$b" # the desired string
aN#zDU>lve15Uwqn
$: echo "$a" # the current string, with embedded metachars
yv[48k2)KMGx{g1b
$: echo "$a" | # pipe it to a sed to clean it
> sed 's/\W/\&/g' # backquote all non-word chars
yv\[48k2\)KMGx\{g1b
$: echo "$a" | sed 's/\W/\&/g'>a # save to a file
$: cat a
yv\[48k2\)KMGx\{g1b
$: echo "sed -E 's/$(<a)/$b/g'">x # save the sed to be run to a file
$: cat x
sed -E 's/yv\[48k2\)KMGx\{g1b/aN#zDU>lve15Uwqn/g'
$: echo $a | . x # source it
aN#zDU>lve15Uwqn
并非完全有必要将所有这些保存到文件中,但它可以让您更轻松地管理您的报价。正如 Ed 在下面提到的,您基本上必须为新密码做同样的事情。
所以你的实际脚本:
echo "$old_pass" | sed 's/\W/\&/g'> old_pat
echo "$new_pass" | sed 's/\W/\&/g'> new_pat
echo "sed -E 's/$(<old_pat)/$(<new_pat)/g'" > src # save the command to a file
echo "$old_pass" | . src # source it
我没有包含 -i
来进行就地编辑,因为您需要先检查该过程。
希望这对某人有所帮助,但总的来说,这是其中一种情况,即使我可能会使用 awk
... 或者更可能的是,老实说,只是重构逻辑。 :)
...您不会在 php 文件中对所有这些密码进行硬编码,对吗? :D
最好在此处使用 perl
,因为它支持 /\Q...\E/
正则表达式模式,可以处理这些标签中的所有字母 字面意思(没有特殊的正则表达式含义) .
这是一个例子:
cat file
abc123
pass=yv[48k2)KMGx{g1b
foobar
现在使用这个 perl
命令:
old_pass='yv[48k2)KMGx{g1b'
new_pass='aN#zDU>lve15Uwqn'
perl -pe "s~\Q${old_pass}\E~\Q$new_pass~g" file
abc123
pass=aN\#zDU\>lve15Uwqn
foobar
如果您没有 perl
,那么您可以使用这个 awk
,它使用 sting 搜索而不使用任何正则表达式:
awk -v old="$old_pass" -v new="$new_pass" 'n=index([=13=], old) {
[=13=] = substr([=13=], 1, n-1) new substr([=13=], n + length(old)) } 1' file
我发现了很多封闭的问题,但并不完全适合我的用例,因此不得不打开一个新问题。
猜猜一个系统的密码由多个配置文件中的所有大小写字母、数字和特殊字符(a-z、A-Z、0-9、#)组成(Web 应用程序使用相同的密码)在主域、子域和所有相关数据库上)。带有密码的此类文件的示例为:
$databases = array (
'default' =>
array (
'default' =>
array (
'database' => 'database_name',
'username' => 'datbase_user',
'password' => 'yv[48k2)KMGx{g1b',
'host' => 'localhost',
'port' => '',
'driver' => 'mysql',
'collation' => 'utf8mb4_general_ci',
'charset' => 'utf8mb4',
'prefix' => '',
),
),
);
我正在尝试编写一个 bash 代码,它接受自动生成的新密码(使用相同的算法 - 所有小写和大写字母、数字和特殊字符),找到所有出现的旧密码在各自父域及其子域的主目录中,并替换为新密码。以下单行工作正常:
grep -rlF "$old_pass" /path/to/directory | xargs sed -i "s/$old_pass/$new_pass/g"
对于仅由字母和数字组成的密码(例如 qVYYgB5bRxUYpHg
)。然而,虽然 grep
部分工作正常,但 sed
部分一旦系统将特殊字符添加到生成的密码(例如 aN#zDU>lve15Uwqn
)给出:
sed -i "s/$old_pass/$new_pass/g" password.php
sed: -e expression #1, char 37: unterminated `s' command
替换所有现有密码的最佳方法是什么,该密码由多个文件中不同变量中存储的所有字母、数字和特殊字符组成?
你的 sed 表达式是错误的,因为你需要转义方括号 [
:
sed -i 's/yv\[48k2)KMGx{g1b/aN#zDU>lve15Uwqn/g' password.php
为避免 shell 参数扩展,请在 sed
表达式中使用单引号。
如果要匹配所有字母、数字和特殊字符(假设标点符号),可以使用class个字符:
sed 's/[[:punct:][:alnum:]]*/NEWPASSWORKD/g' password.php
我认为自动生成的密码的可能排列可能超出了您将能够轻松适应 sed
的范围,但问题的症结在于保护元字符。对于这个具体的例子:
$: echo "$b" # the desired string
aN#zDU>lve15Uwqn
$: echo "$a" # the current string, with embedded metachars
yv[48k2)KMGx{g1b
$: echo "$a" | # pipe it to a sed to clean it
> sed 's/\W/\&/g' # backquote all non-word chars
yv\[48k2\)KMGx\{g1b
$: echo "$a" | sed 's/\W/\&/g'>a # save to a file
$: cat a
yv\[48k2\)KMGx\{g1b
$: echo "sed -E 's/$(<a)/$b/g'">x # save the sed to be run to a file
$: cat x
sed -E 's/yv\[48k2\)KMGx\{g1b/aN#zDU>lve15Uwqn/g'
$: echo $a | . x # source it
aN#zDU>lve15Uwqn
并非完全有必要将所有这些保存到文件中,但它可以让您更轻松地管理您的报价。正如 Ed 在下面提到的,您基本上必须为新密码做同样的事情。
所以你的实际脚本:
echo "$old_pass" | sed 's/\W/\&/g'> old_pat
echo "$new_pass" | sed 's/\W/\&/g'> new_pat
echo "sed -E 's/$(<old_pat)/$(<new_pat)/g'" > src # save the command to a file
echo "$old_pass" | . src # source it
我没有包含 -i
来进行就地编辑,因为您需要先检查该过程。
希望这对某人有所帮助,但总的来说,这是其中一种情况,即使我可能会使用 awk
... 或者更可能的是,老实说,只是重构逻辑。 :)
...您不会在 php 文件中对所有这些密码进行硬编码,对吗? :D
最好在此处使用 perl
,因为它支持 /\Q...\E/
正则表达式模式,可以处理这些标签中的所有字母 字面意思(没有特殊的正则表达式含义) .
这是一个例子:
cat file
abc123
pass=yv[48k2)KMGx{g1b
foobar
现在使用这个 perl
命令:
old_pass='yv[48k2)KMGx{g1b'
new_pass='aN#zDU>lve15Uwqn'
perl -pe "s~\Q${old_pass}\E~\Q$new_pass~g" file
abc123
pass=aN\#zDU\>lve15Uwqn
foobar
如果您没有 perl
,那么您可以使用这个 awk
,它使用 sting 搜索而不使用任何正则表达式:
awk -v old="$old_pass" -v new="$new_pass" 'n=index([=13=], old) {
[=13=] = substr([=13=], 1, n-1) new substr([=13=], n + length(old)) } 1' file