2014-01-15 37 views
0

我能在幾條命令中搜索並替換文件中的多行嗎?用另一條多行代替文件中的多行

我試圖用,dhcp_primary內的唯一故障轉移塊替換dhcp_primary中的3個故障轉移塊。

我的目標是將dhcpd.conf從主dhcp複製到輔助(更多信息請參閱:http://www.madboa.com/geek/dhcp-failover/)。只有當配置完全相同時,故障轉移纔會起作用,當然除故障轉移塊外;正如你所看到的是網站的例子。 所以我想複製這個文件,但保留次要的故障轉移信息。

dhcp_primary

// some lines above 
failover peer "A" { 
... 
} 
failover peer "B" { 
... 
} 
failover peer "C" { 
... 
} 
// some lines below 

dhcp_secondary

// some different lines above 
failover peer "D" { 
... 
} 
// some different lines below 

預期的輸出必須是:

// some lines above 
failover peer "D" { 
... 
} 
// some lines below 

我已經可以提取故障轉移塊:

awk '/^failover/,/^}$/' dhcp_a 

awk '/^failover/,/^}$/' dhcp_b 

但我不知道如何繼續。

在此先感謝。

編輯:我的目標的更多細節。

+0

我不熟悉故障轉移塊。數字「111」和「222」的用途是什麼? 'dhcp_a'和'dhcp_b'是兩個單獨的文件,還是同一個文件中的塊? –

+0

在這裏,數字111和222代表一些線條。故障轉移將一個在另一個之下而不在其間,但這些塊上面有一些行,並在這些塊下面有一些行。 而dhcp_a和dhcp_b將分隔文件。 – Jeelo

+0

在給定的故障切換塊中是否可以嵌套大括號?像'failover peer「D」{... subnet {...}}'?並且它在主要文件中的次要故障轉移塊結束時是否是任意的? (例如,你可以在文件的開頭有嗎?) –

回答

2

你可以試試:

awk -f a.awk dhcp_b dhcp_a 

其中a.awk是:

/^failover/,/^}$/{ 
    if (NR==FNR) { 
     blk=blk $0 RS 
     next 
    } 
    if (++i==1) { 
     printf "%s",blk 
    } 
    next 
} 
NR!=FNR{ print } 
+1

+1這可能是我第一次見到'/ a /,/ b /'有用! nit-pick - 'NR!= FNR {print}'可以縮寫爲'NR!= FNR'。 –

+1

@EdMorton謝謝,我只是想我應該嘗試使用OP中使用範圍表達式的代碼..但我很快發現它的確不是非常靈活。 –

+0

謝謝HåkonHægland,您的解決方案工作得很好。 – Jeelo

0

文件是否僅此結構和類型的內容

NewFile=./FileName 

head -1 dhcp_a > ${NewFile} 
sed -n '1!{$!p;};}' dhcp_b >> ${NewFile} 
tail -1 dhcp_a >> ${NewFile} 

只取dhcp_b的dhcp_a和塊內容頭部和尾部

如果文件是(約內容)更大的使用類似/故障切換/,/} /在SED塊分隔符,但它依賴於實際的內容

+0

周圍的內容比較大,但我不知道如何在sed中使用塊分隔符。 – Jeelo

+0

提供足夠的文件樣本(足夠的部分)來估計不定位在文件的其他部分的定界符 – NeronLeVelu

+0

文件的示例如下: http://www.madboa.com/geek/dhcp -failover/ 在「配置主服務器」和「配置輔助服務器」下面我的目標是將dhcpd.conf從主服務器複製到備用服務器。 這樣,le配置將是相同的,但我必須保留故障轉移塊。 – Jeelo

1

這可能會爲你工作(GNU SED)的:

sed -n '/^failover peer/,/^}/p' dhcp_b | 
sed -e '/^failover peer/,/^}/!b;r /dev/stdin' -e 'd' dhcp_a 
+0

我對這個命令有一些問題: - b:未找到事件。我想在FreeBSD下,遺憾的是忘記了這些信息。 – Jeelo

+0

@Jeelo'/ dev/stdin'是GNU特有的。但是我認爲你沒有複製解決方案,因爲'/.../!b'避免了'r'命令接受2個地址的問題。 – potong

0
$ cat tst.awk 
/^failover/ { inRec = 1 } 

{ 
    if (NR == FNR) { 
     if (inRec) { 
      rec = rec $0 ORS 
     } 
    } 
    else { 
     if (inRec) { 
      printf "%s", rec 
      rec = "" 
     } 
     else { 
      print 
     } 
    } 
} 

/^}/ { inRec = 0 } 

$ awk -f tst.awk secondary primary 
// some lines above 
failover peer "D" { 
... 
} 
// some lines below 
+0

這個解決方案工作得很好。謝謝埃德莫頓的幫助。 – Jeelo