簡體   English   中英

使用sed進行模式匹配后的多線模式

[英]Multiline pattern after pattern match using sed

我有一個由多個部分組成的配置文件,其中許多部分包含一個具有相同名稱的屬性,讓它成為host 我只需要替換一個特定部分的host屬性。 這是文件:

section1 {
  ...
  setting1 = "true"
  ...
  host = "localhost"
  ...
}
section2 {
  ...
  host = "whatever"
  ...
}

我想用其他東西替換section2host值。 請注意,它們之間可能有任意數量的行,標記為...

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 '
  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()不支持。
        但是, GNU awk通過其非標准的gensub()函數提供了捕獲組引用; 見下文。
    • GNU Awk解決方案:使用非標准gensub()函數可以使用捕獲組( \\\\1指的是第一個捕獲的組,...),這使得替換更加健壯和方便。

      • gensub() ,與sub()不同,它不修改輸入字符串而是返回修改后的副本 - 因此需要將其分配給$0
      • 1作為第3個參數告訴gensub()只替換1次出現。
  • 1是簡單打印結果記錄的常用簡寫。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM