這是此處提出和回答的問題的擴展:使用 sed 僅在第一次出現的模式匹配後查找並替換文件中的文本
問題是:我需要執行查找和替換,但是僅有的第一次出現後pattern1
緊接著出現pattern2
。這就是pattern3
必須進行查找和替換的地方。
使用連結問題中範例文件的變體:
Server 'Test AB'
option type 'sa'
option port '1234'
option timeout '60'
Server 'Test AB'
option type 'sb'
option port '1234'
option timeout '60'
Server 'Test EF'
option type 'sa'
option port '1234'
option timeout '60'
Server 'Test GH'
option type 'sa'
option port '1234'
option timeout '60'
我需要這個:
Server 'Test AB'
option type 'sa'
option port '1234'
option timeout '60'
Server 'Test AB'
option type 'sb'
option port '9876'
option timeout '60'
Server 'Test EF'
option type 'sa'
option port '1234'
option timeout '60'
Server 'Test GH'
option type 'sa'
option port '1234'
option timeout '60'
前兩個Server
名字是相同的。每個伺服器的情況option type
都不同。我需要匹配特定Server
名稱 ( Test AB
),然後匹配option type
( sb
),然後更改連接埠號碼。
我不知道如何使多個模式在邏輯中連接起來AND
。
有小費嗎?sed
或awk
解決方案是首選(但對於鐵桿頸鬍子尋找真實的挑戰,嘗試用純 BASH 替換來完成。 BASH 5 以上版本就可以了)。謝謝。
答案1
sed
允許您在表單中指定位址範圍addr1,addr2
。連結的答案使用一個範圍。現在您需要嵌套範圍。
sed "
/^Server 'Test AB'$/,/^$/ {
/option type 'sb'/,/option port '/ s/option port '.*'/option port '2222'/
}" file
這意味著:從(並包括)一行Server 'Test AB'
到(並包括)下一個空白行應用裡面的程式碼{}
。
裡面的程式碼{}
意味著:從(並包含)包含應用指令的行option type 'sb'
到(並包含)包含option port '
應用s/…/…/
指令的行。
該s/…/…/
命令的含義是:在每一行中將第一次出現的option port '.*'
(.*
貪婪地匹配零個或多個字元)替換為option port '2222'
。
筆記:
幸運的是,我們可以使用空白行來結束範圍。如果沒有它們,我們會很想指定從 到
Server
的範圍Server
。問題是從Server 'Test AB'
到下一次出現的第一個範圍Server
將包括第二次出現的Server 'Test AB'
;且同一段程式碼sed
偵測到的範圍不能重疊。addr1,addr2
實際上,第二次出現的Server 'Test AB'
不會被視為新範圍的開始,因此{}
不會對該部分中的行執行其中的程式碼。^
和$
分別是行首和行尾的錨點。我將它們與 一起使用Server 'Test AB'
,但我故意不將它們與 一起使用option type 'sb'
。根據您的需求調整代碼。我使用雙引號是因為資料包含單引號。通常你需要
$
用雙引號進行轉義,但這裡我們在/
每個$
;後面加引號。$/
不是 shell 變數的有效名稱,也不是 shell 想要擴展的任何名稱,因此無需轉義$
.