我想在 CLI 中编辑一些配置文件,不用所见即所得编辑器,而是使用sed
。
有没有最佳做法来做到这一点?
以下是我所指的几个例子:
配置文件示例 1
配置文件中的一行可能是这样的:
foo_option /bar/baz
编辑后应如下所示:
#foo_option /bar/baz
foo_option /new/opt
配置文件示例 2
配置文件中的一行可能是这样的:
foo_option=/bar/baz
编辑后应如下所示:
#foo_option=/bar/baz
foo_option=/new/opt
我认为流编辑器sed
是首选工具,我已经对它进行过实验:
sed -e 's/\(^foo_option .*$\)/#\1/' /path/to/conf.file
和:
sed -e 's/^foo_option .*$/foo_option /new/opt/' /path/to/conf.file
但是我怎样才能同时进行这两项更改(两行,一行注释掉,一行包含新内容)?
这真的是最佳做法sed
吗?
答案1
我不知道这是否是“最佳实践”,但这sed
方面的代码相对简单:
sed '/^foo_option / {s/^/#/; a\
foo_option /new/opt
}' /path/to/conf.file
它解决了示例 1。要解决示例 2,您需要在代码foo_option
中用 替换每个出现的(有两次出现,请注意尾随空格)。foo_option=
sed
=
解决这两个示例的通用代码更复杂,因为您附加的内容取决于旧行中的存在;因此您不能使用a
固定字符串。试试这个:
sed '/^foo_option[= ]/ {
h; s/^/#/; p
g; s|\([= ]\).*|\1/new/opt|
}' /path/to/conf.file
上述代码两次使用了原始行。首先,它将行从模式空间复制到保留空间 ( h
),将其添加#
到前面并打印模式空间 ( p
)。接下来,它从保留空间 ( g
) 复制回来并放置/new/opt
在正确的位置;这次打印模式空间,因为sed
(没有-n
) 在处理完行后默认会打印(不需要p
)。
笔记:
我
|
在第二个中使用了s
,而不是/
,因为/new/opt
包含/
。您尝试使用s/^foo_option .*$/foo_option /new/opt/
无效,字符太多/
。一般来说您可以使用几乎任何字符。在您尝试时,您
^foo_option
在模式中使用了s
来匹配正确的行;然后您需要在替换中使用它(作为\1
或文字foo_option
)。更好的方法是使用正则表达式匹配来处理行,就像我所做的那样:/^foo_option /
或 so。然后以下命令(或{ }
块)不需要检查它是否是正确的行,您知道它是正确的。您可以使用s
; 以外的命令,并且s
通常可以大大简化。即使在添加的简单情况下,#
我也更喜欢/^foo_option / s/^/#/
。s/\(^foo_option \)/#\1/
前者的代码更具可读性,而且是正确的方法。在正则表达式中
*
是贪婪的,所以.*$
(你使用它)并不真正需要$
。