我在配置文件中使用sed替换字符串。
用户必须输入字符串salt
,然后在配置文件中替换此salt
字符串:
Sample config file myconfig.conf
CONFIG_SALT_VALUE=SOME_DUMMY_VALUE
我使用该命令将虚拟值替换为用户输入的salt
值。
sed -i s/^CONFIG_SALT_VALUE.*/CONFIG_SALT_VALUE=$salt/g" ./myconfig.conf
问题:$salt
的值可以包含任何字符,因此如果$salt
包含/
(如12d/dfs
),那么我的上述sed命令符。
我可以将分隔符更改为!
,但如果$salt
包含amgh!fhf
,那么我的sed命令将会中断。
我该如何处理这个问题?
答案 0 :(得分:1)
You can use almost any character as sed
delimiter。但是,正如你在问题中提到的那样,不断改变它是脆弱的。
使用awk
代替,对该行进行一些解析可能很有用:
awk 'BEGIN{repl=ARGV[1]; ARGV[1]=""; FS=OFS="="}
$1 == "CONFIG_SALT_VALUE" {$2=repl}
1' "$salt" file
作为一个班轮:
awk 'BEGIN{repl=ARGV[1]; ARGV[1]=""; FS=OFS="="} $1 == "CONFIG_SALT_VALUE" {$2=repl}1' "$salt" file
这会将=
设置为字段分隔符。然后,它检查一行包含CONFIG_SALT_VALUE
作为参数名称。发生这种情况时,它会将值替换为给定值。
为防止像$salt
这样的foo\\bar
中的值被解释,正如其他人在我的原始答案中所评论的那样,我们有诀窍:
awk 'BEGIN{repl=ARGV[1]; ARGV[1]=""} ...' "$var" file
这使用How to use variable including special symbol in awk?中的答案,其中Ed Morton说
在没有反斜杠的情况下将shell变量传递给awk的方法 解释是在arg列表中传递它而不是填充awk 脚本之外的变量。
然后
填充awk变量后,需要设置
ARGV[1]=""
避免shell变量值也被视为文件名。 与传递变量的任何其他方式不同,使用的是所有字符 这种方式的变量按字面处理,没有“特殊”含义。
这不会进行就地编辑,但您可以重定向到另一个文件,然后替换原始文件:
awk '...' file > tmp_file && mv tmp_file file