使用sed修改配置文件到键值

在shell脚本中,需要修改某个配置文件的配置项。比较简单粗暴的方式是,先sed删除掉匹配行,然后再在配置文件末尾echo方式添加一行。但是这种方式会导致配置文件很混乱,并且对于一些标准的"段落块"INI配置文件会引发问题。

如果有大量的配置需要修改,并且希望标准化配置方法,可以采用配置修改工具augeas。不过,对于短小简单的shell脚本,可以使用sed来实现配置修改。

使用sed设置配置文件 key=value

举例,需要将/etc/libvirt/qemu.conf默认配置

auto_dump_path = "/var/lib/libvirt/qemu/dump"

修改成自定义目录;

auto_dump_path = "/myapp/qemu/dump"

命令如下:

sed -i -e '/^auto_dump_path =/ s/= .*/= "\/myapp\/qemu\/dump"/' /etc/libvirt/qemu.conf

解释:

  • -i表示sed将处理结果直接写入到输入文件,这样就不会打印输出

  • /^auto_dump_path =/ 表示匹配//之间的内容,这里字符串开头加了^是为了匹配实际生效的非注释行,就不会匹配到#auto_dump_path =这样的配置注释内容。^表示行首。

  • s/OLD/NEW/是执行一个替换,OLD字符串是一个规则匹配到正则表达式,将被替换成NEW字符串。

  • 在正则表达式中,.*表示"匹配任何内容",所以这里= .*就会匹配上等于符号,空格以及其他任何内容。

  • 在替换内容中= "\/myapp\/qemu\/dump",使用\/\符号是转义符。

sed参数传递(参数中包含/)

上述一条命令修改配置文件的键值虽然方便,但是在shell脚本中,我们会使用变量,sed是如何使用shell中的变量呢?

方法很简单,就是将我们习惯使用的''修改成"",这样在shell脚本中使用sed时,会自动实现变量替换(因为在shell中,双引号中会解析变量):

然而问题来了,由于传递的value中包含了/作为路径,对于sed来说,命令分隔符默认就是/,这会导致传递value中包含的/被sed解析成命令分隔符。

这个问题在Environment variable substitution in sed提供了解决思路:

sed实际上可以使用其他字符来代替/作为分隔符,所以如果你传递的参数中包含了/,你可以用其他不可能包含在参数中的字符来作为sed的分隔符。例如使用@或者#。所以我们的脚本就可以修改成使用#作为sed分隔符:

sed工具已经考虑过这样的特殊字符操作,不需要使用转义符就可以轻松实现行编辑。

现在我们的脚本改进如下:

配置格式适配

仔细观察Linux系统配置文件,常见有两种格式的配置赋值方式,主要区别是=前后是否存在空格

此外,数值通常不使用引号,字符串则使用引号。

通过以下函数判断传入的参数是否是整数值来确定添加引号,以及通过分析现有配置文件格式的=前后是否有空格来设置格式

参考

Last updated

Was this helpful?