最终目标是在文件中替换包含密码的行(可以包含任何字符):
...
passw=old#$#$@$#@%{}[]
...
我有替换字符串变量: (别介意现在的双引号)
$old="passw=old#$#$@$#@%{}[]"
$new="passw=new#$#$@$#@%{}[]"
如果我使用简单的sed -i "s#$old#$new#g" file.txt"
,它显然无法正常工作,因为特殊字符会破坏语法。
要使其正常工作,我需要使用\
转义所有特殊字符,例如:\[
我尝试使用这样的东西:
esc=$("$old" | sed 's/[][`~!@#$%^&*()-_=+{}\|;:",<.>/?'"'"']/\\&/g'
然而,它给了我以下错误:
sed: -e expression #1, char42: Invalid range end
非常感谢任何帮助!
答案 0 :(得分:2)
awk
救援!
请注意,替换基于正则表达式,awk
中的搜索字符串需要转义特殊字符,sed
中的搜索和替换字符串都需要转义。这需要预处理字符串。或者,如果输入文件是结构化的,则可以尝试字符串相等性检查
例如,
$ awk -v old='old#$#$@$#@%{}[]' \
-v new='[]{}new#$#$@$#@%' \
-v key='passw=' '"^"key{line=$0;
sub(key,"",line);
if(line==old) $0=key new}1' file
在输入文件上运行
passw=old#$#$@$#@%{}[]
some other line with old#$#$@$#@%{}[]
将生成
pasw=[]{}new#$#$@$#@%
some other line with old#$#$@$#@%{}[]
您还可以对完整的key=value
匹配进行相等检查,如下所示
$ awk -v old='old#$#$@$#@%{}[]' \
-v new='[]{}new#$#$@$#@%' \
-v key='passw=' '$0==key old{$0=key new}1' file
或通过搜索和替换字符串进一步简化包括key=
前缀
awk -v old='passw=old#$#$@$#@%{}[]' \
-v new='passw=[]{}new#$#$@$#@%' \
'$0==old{$0=new}1' file
这些假设您的密码记录在一个单独的行上。如果它不是一个有效的假设,您可以将RS和ORS设置为' '
并删除输出文件的最后一个字符(添加的最后一个ORS)。另一个解决方案可能是迭代循环中的字段(例如for(i=1;i<=NF;i++) if($i==old) $i=new...
)
答案 1 :(得分:1)
如果没有适当的逃避,你将无法实现它。我尝试了sed,perl等,但所有这些都破了,特别是在chars {}和[]中。
你可以同时使用sed来逃避所有非常规字符 在下面的例子中,我逃避了不是文本的所有内容(a-z和A-Z)而不是数字(0-9)
$ cat file14
passw=old#$#$@$#@%{}[]
$ old='passw=old#$#$@$#@%{}[]' && echo "$old" #mind the single quotes.
passw=old#$#$@$#@%{}[]
$ new='passw=new$#$#$$0-.?!@#$%^&*()_+@$#@%[]{}' && echo "$new"
passw=new$#$#$$0-.?!@#$%^&*()_+@$#@%[]{}
$ old=$(sed 's/[^a-zA-Z0-9]/\\&/g' <<<"$old") && echo "$old"
passw\=old\#\$\#\$\@\$\#\@\%\{\}\[\]
$ new=$(sed 's/[^a-zA-Z0-9]/\\&/g' <<<"$new") && echo "$new"
passw\=new\$\#\$\#\$\$0\-\.\?\!\@\#\$\%\^\&\*\(\)\_\+\@\$\#\@\%\[\]\{\}
$ sed -r "s/$old/$new/" file14
passw=new$#$#$$0-.?!@#$%^&*()_+@$#@%[]{}