我有一个由多个部分组成的配置文件,其中许多部分包含一个具有相同名称的属性,让它为host
。我只需要替换某个特定部分的host
属性。这是文件:
section1 {
...
setting1 = "true"
...
host = "localhost"
...
}
section2 {
...
host = "whatever"
...
}
我想用其他内容替换host
的{{1}}值。请注意,中间可能有任意数量的行,标记为section2
答案 0 :(得分:2)
sed -i.bak '/^section2 {/,/^}/s/host .*/host = "newvalue"/' file
这将在section2 {
和下一个}
之间进行搜索,从而更改所有host =
次出现。 GNU sed语法,您应该在OSX上使用例如sed -i '' ...
。
答案 1 :(得分:1)
awk
救援!
$ awk 'BEGIN{RS=ORS="\n}"}
/section2/{sub("host =[^\n]*", "host = \"newvalue\"")}NF' file
section1 {
...
setting1 = "true"
...
host = "localhost"
...
}
section2 {
...
host = "newvalue"
...
}
定义记录结构,找到相应的记录并替换。
答案 2 :(得分:0)
Joao Morais's answer可能是最好的选择。
使用awk
解决方案(更正,更强大的karakfa's answer版本)来补充它:
awk
:谢谢,@EdMorton awk '
BEGIN{ RS=ORS="}\n" }
/^section2/ { $0 =gensub(/(\n *host = )[^\n]*/, "\\1\"new value\"", 1) }
1' file
mawk
(不太健壮;也适用于GNU awk
):awk '
BEGIN{ RS=ORS="}\n" }
/^section2/ { sub(/ host = [^\n]*/, " host = \"new value\"") }
1' file
注意:由于使用了多字符RS
值,因此这两种解决方案都不适用于BSD / OSX awk
;使它工作需要更多的努力。
<强>解释强>
RS=ORS="}\n"
告诉awk
将输入分成}\n
个实例(通过特殊变量RS
,输入记录分隔符),并使用输出的相同分隔符(通过ORS
,输出记录分隔符)。
/^section2/
在每条记录的开头处与文字section
匹配。
Mawk解决方案:{ sub(/ host = [^\n]*/, " host = \"new value\"") }
使用新值替换密钥host
的值。
([^\n]*)
匹配,因为只有.*
会匹配记录的结尾,并且会有换行符。host
密钥,例如与
sub("/(\n *host = )...
),但您需要捕获组引用以在替换值中保留相同数量的前导空格,sub()
不支持。
但是, GNU awk
通过其非标准gensub()
函数提供捕获组引用;见下文。 GNU Awk解决方案:使用非标准gensub()
函数可以使用捕获组(\\1
指的是第一个捕获的组,...),这使得替换更多健壮,更方便。
gensub()
,与sub()
不同,不会修改输入字符串,而是返回修改后的副本 - 因此需要将其分配给$0
。< / LI>
1
,因为第3个参数告诉gensub()
仅替换 1 事件。 1
是简单打印结果记录的常用简写。