sed转义用户输入字符串

时间:2016-01-06 17:42:24

标签: regex bash awk sed

我在配置文件中使用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命令将会中断。

我该如何处理这个问题?

1 个答案:

答案 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