[英]Multiline pattern after pattern match using sed
我有一個由多個部分組成的配置文件,其中許多部分包含一個具有相同名稱的屬性,讓它成為host
。 我只需要替換一個特定部分的host
屬性。 這是文件:
section1 {
...
setting1 = "true"
...
host = "localhost"
...
}
section2 {
...
host = "whatever"
...
}
我想用其他東西替換section2
的host
值。 請注意,它們之間可能有任意數量的行,標記為...
sed -i.bak '/^section2 {/,/^}/s/host .*/host = "newvalue"/' file
這將在section2 {
和next }
之間進行搜索,更改所有host =
occurences。 GNU sed語法,你應該在OSX上使用例如sed -i '' ...
awk
來救援!
$ awk 'BEGIN{RS=ORS="\n}"}
/section2/{sub("host =[^\n]*", "host = \"newvalue\"")}NF' file
section1 {
...
setting1 = "true"
...
host = "localhost"
...
}
section2 {
...
host = "newvalue"
...
}
定義記錄結構,找到相應的記錄並替換。
Joao Morais的回答可能是最好的選擇。
用awk
解決方案來補充它( karakfa答案的更正,更強大的版本):
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\\"") }
用{ sub(/ host = [^\\n]*/, " host = \\"new value\\"") }
替換密鑰host
的值。
([^\\n]*)
,因為只有.*
會匹配記錄的末尾,跨換行符。 host
密鑰,例如 sub("/(\\n *host = )...
),但是您需要捕獲組引用以在替換值中保留相同數量的前導空格,而sub()
不支持。 awk
通過其非標准的gensub()
函數提供了捕獲組引用; 見下文。 GNU Awk解決方案:使用非標准gensub()
函數可以使用捕獲組( \\\\1
指的是第一個捕獲的組,...),這使得替換更加健壯和方便。
gensub()
,與sub()
不同,它不修改輸入字符串而是返回修改后的副本 - 因此需要將其分配給$0
。 1
作為第3個參數告訴gensub()
只替換1次出現。 1
是簡單打印結果記錄的常用簡寫。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.