2017-10-04 74 views
3

兩行之間的替換文本比方說,我有一個與此內容稱爲original.txt文件:存儲在一個變量文件的內容在sed

紅色
藍色

食品

灰色
白色

我也有一個與此內容稱爲new.txt文件:

綠色
黑色
黃色
紫色

現在我想編寫一個腳本,以取代bluegray之間的界限在original.txt內容new.txt,所以它給了我這個結果:



綠色

黃色
紫色
灰色
白色

我寫這段代碼爲宗旨(新文件的名稱並不總是因此它存儲在一個變量中):

newtext="new.txt" 

sed -i "/blue/,/gray/{ 
    r $newtext 
    d 
}" original.txt 

但是,在運行時,我得到這個廢話,而不是:

red 
green 
black 
yellow 
purplegreen 
black 
yellow 
purplegreen 
black 
yellow 
purplegreen 
black 
yellow 
purplegreen 
black 
yellow 
purplewhite 

我在做什麼錯?

+0

你只想從第二個文件插入線一次,並非每次遇到範圍內的一條線。 – potong

回答

6

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

sed '/blue/,/gray/!b;//!d;/blue/r file2' file1 

對於bluegray行之間的範圍,刪除不符合第一或該範圍內的最後幾行和讀取線要在範圍的最後一行之前插入的行。

編輯:

第一sed命令/blue/,/grey/!b一個範圍內的行,即,含有高達blue一個線和包括含有gray的線之間的範圍內的線的匹配。 !b部分表示如果行不在該範圍內,則脫離sed命令,即不對這些行進行任何進一步的sed處理,只是按正常打印。

以下sed命令只會影響範圍在bluegray之間的那些行。

第二個命令//!d表示刪除那些與範圍的開始/結束不匹配的行,即bluegray//使用先前的/.../命令中的正則表達式。注:刪除命令會終止該行的任何進一步sed處理。

以下sed命令只會影響包含bluegray的行。

第三條命令與包含blue的行相匹配,並從file2讀入行。

N.B.包含bluegrey的行由sed自然處理,並在將下一行讀入模式空間之前進行打印,而不在bluegray之間的行也是如此。

一種替代方案:

sed '/blue/,/gray/!b;//!d;/gray/e cat file2' file1 

而另:

sed -ne '/blue/{p;r file2' -e ':a;n;/gray/!ba};p' file1 
+0

謝謝!它工作得很好,我只需要添加'// a'來添加一個新行,因爲'purple'和'gray'正在合併。你介意解釋每個命令做了什麼嗎?另外,有沒有辦法避免在指令中寫兩次'blue'? – Stealth

+0

如果你可以添加這些'sed'命令的工作方式,那確實是非常有用的。 – codeforester

+0

也想知道命令'//!d'的'//',請問有人能說明一下嗎? – CWLiu

2

sed的是S /老/新/,這是所有。爲別的,你應該使用AWK:

$ awk 'NR==FNR{new = new $0 ORS; next} /gray/{f=0} !f{print} /blue/{printf "%s",new; f=1}' new.txt original.txt 
red 
blue 
green 
black 
yellow 
purple 
gray 
white 

以上在任何AWK工作在任何UNIX系統中的任何外殼,並且不需要任何的開始/結束正則表達式的重複。非常重要的是,它也可以簡單地建立在現在或將來做任何你想要的事情上!例如,爲了能夠指定的開始和結束的正則表達式作爲參數是:

$ awk -v beg='blue' -v end='gray' 'NR==FNR{new = new $0 ORS; next} $0~end{f=0} !f{print} $0~beg{printf "%s",new; f=1}' new.txt original.txt 

廣告,那麼你可以改變他們:你可能想要做

$ awk -v beg='water' -v end='tree' 'NR==FNR{new = new $0 ORS; next} $0~end{f=0} !f{print} $0~beg{printf "%s",new; f=1}' new.txt original.txt 
red 
blue 
water 
green 
black 
yellow 
purple 
tree 
gray 
white 

任何事情都是隻使用一個簡單的重排相同的結構,例如不打印開始行:

$ awk -v beg='blue' -v end='gray' 'NR==FNR{new = new $0 ORS; next} $0~end{f=0} $0~beg{printf "%s",new; f=1} !f{print}' new.txt original.txt 
red 
green 
black 
yellow 
purple 
gray 
white 

和類似的調整,以不打印結尾行或者不同時打印或做別的事....

+0

實際上並沒有檢查開始和結束regexp是否在替換之前匹配...但沒有被OP提及爲需求,所以我想這不是問題... – Sundeep

+0

謝謝你的答案。我使用sed是出於舒適的原因,因爲它是我一直使用的語法,並且具有更短更簡潔的語法;我也需要一個私人項目,所以我不需要可移植性;我確信這個任務在sed中是可能的,所以我主要想知道我的代碼中的錯誤在哪裏。 但我給你的理由是,我應該開始使用awk來處理這些情況,因爲依賴於標準和便攜式解決方案總是更好,我再次感謝你爲我解釋如何。 :) – Stealth

+1

'清潔語法'???你一定在開玩笑。我已經使用了四十年的sed,並且通常不能分辨給定的腳本是要讀取文件還是召喚上帝cthulu。所有的我們自己,我想..是的,你應該真正學習awk - 你會驚訝於一切變得更簡單和更一致。 –