Linux高级文本处理之sed(三)
sed高級命令
sed允許將多行內容讀取到模式空間,這樣你就可以匹配跨越多行的內容。本篇筆記主要介紹這些命令,它們能夠創建多行模式空間并且處理之。其中,N/D/P這三個多行命令分別對應于小寫的n/d/p命令,后者我們在上一篇已經介紹。它們的功能是類似的,區別在于命令影響的內容不同。例如D命令與d命令同樣是刪除模式空間的內容,只不過d命令會刪除模式空間中所有的內容,而D命令僅會刪除模式空間中的第一行。
一、讀下一行:N
N命令將下一行的內容讀取到當前模式空間,但是與n命令不一樣的地方是N命令并沒有直接輸出當前模式空間中的行,而是把下一行追加到當前模式空間,兩行之間用回車符\n連接,如下圖所示:
說明:模式空間包含多行之后,正則表達式的^/$符號的意思就變了,^是匹配模式空間的最開始而非行首,$是匹配模式空間的最后位置而非行尾。
實例1:替換以下文本中的”Owner and Operator Guide”為”Installation Guide”
[root@localhost?~]#?cat?text? Consult?Section?3.1?in?the?Owner?and?Operator Guide?for?a?description?of?the?tape?drives available?on?your?system.[root@localhost?~]#?sed?'/Operator$/{N;s/Owner?and?Operator\nGuide/Installation?Guide/}'?text Consult?Section?3.1?in?the?Installation?Guide?for?a?description?of?the?tape?drives available?on?your?system.不過這個例子有兩個局限:
● 我們知道Owner and Operator Guide分割的位置;
● 執行替換命令后,前后兩行拼接在一起,導致這行過長;
第二點,可以這樣解決:
[root@localhost?~]#?sed?'/Operator$/{N;s/Owner?and?Operator\nGuide/Installation?Guide\n/}'?text Consult?Section?3.1?in?the?Installation?Guidefor?a?description?of?the?tape?drives available?on?your?system.實例2:Owener and Operator Guide出現在多行的多個位置
[root@localhost?~]#?cat?text???#原文文本 Consult?Section?3.1?in?the?Owner?and?Operator Guide?for?a?description?of?the?tape?drives available?on?your?system.Look?in?the?Owner?and?Operator?Guide?shipped?with?your?system.Two?manuals?are?provided?including?the?Owner?and Operator?Guide?and?the?User?Guide.The?Owner?and?Operator?Guide?is?shipped?with?your?system.[root@localhost?~]#?sed?'s/Owner?and?Operator?Guide/Installation?Guide/ >??/Owner/{ >??N >??s/?*\n/?/ >??s/Owner?and?Operator?Guide?*/Installation?Guide\ >??/ >?}'?text Consult?Section?3.1?in?the?Installation?Guidefor?a?description?of?the?tape?drives available?on?your?system.Look?in?the?Installation?Guide?shipped?with?your?system.Two?manuals?are?provided?including?the?Installation?Guideand?the?User?Guide.The?Installation?Guide?is?shipped?with?your?system.說明:這里我們首先將在單行出現的Owner and Operator Guide替換為Installation Guide,然后再尋找匹配Owner的行,匹配后讀取下一行的內容到模式空間,并且將中間的換行符替換成空格,最后再替換Owner and Operator Guide。
看上去sed命令中作了兩次替換是多余的。實際上,如果去掉第一次替換,再運行腳本,就會發現輸出存在兩個問題。一個是結果中最后一行不會被替換(在某些版本的sed中甚至不會被輸出)。這是因為最后一行匹配了"Owner",執行N命令,但是已經到了文件末尾,某些版本就會直接打印這行再退出,而另外一些版本則是不作出打印立即退出。對于這個問題可以通過命令"$!N"來解決。這表示N命令對最后一行不起作用。另外一個問題是"look manuals"一段被拆為兩行,而且與下一段的空行被刪除了。這是因為內嵌的換行符被替換的結果。因此,sed中做兩次替換一點也不是多余的。
二、刪除行:D
該命令刪除模式空間中第一行的內容,而它對應的小d命令刪除模式空間的所有內容。D不會導致讀入新行,相反它會回到最初的編輯命令,重要應用在模式空間剩余的內容上。
實例1:現在我們要刪除文件text多余的空行,將多個空行縮減成一行。
文件內容:
[root@localhost?~]#?cat?text? This?line?is?followed?by?1?blank?line.This?line?is?followed?by?2?blank?line.This?line?is?followed?by?3?blank?line.This?line?is?followed?by?4?blank?line.This?is?the?end.使用d命令刪除如下:
[root@localhost?~]#?sed?'/^$/{N;/^\n$/d}'?text? This?line?is?followed?by?1?blank?line.This?line?is?followed?by?2?blank?line. This?line?is?followed?by?3?blank?line.This?line?is?followed?by?4?blank?line. This?is?the?end.說明:我們會發現一個奇怪的結果,奇數個數的相連空行已經被合并成一行,但是偶數個數的卻全部被刪除了。造成這樣的原因需要重新翻譯下上面的命令,當匹配一個空行是,將下一行也讀取到模式空間,然后若下一行也是空行,則模式空間中的內容應該是\n,因此匹配^\n$,從而執行d命令會將模式空間中的內容清空,結果就是相連的兩個空行都被刪除。這樣就可以理解為什么相連奇數個空行的情況下是正常的,而偶數個數就有問題了。
使用D命令刪除如下:
[root@localhost?~]#?sed?'/^$/{N;/^\n$/D}'?text? This?line?is?followed?by?1?blank?line.This?line?is?followed?by?2?blank?line.This?line?is?followed?by?3?blank?line.This?line?is?followed?by?4?blank?line.This?is?the?end.說明:D命令只會刪除模式空間的第一行,而且刪除后會重新在模式空間的內容上執行編輯命令,類似形成一個循環,前提是相連的都是空行。當匹配一個空行時,N讀取下一行內容,此時匹配^\n$導致模式空間中的第一行被刪除。現在模式空間中的內容是空的,重新執行編輯命令,此時匹配/^$/。繼續讀取下一行,當下一行依然為空行時,重復之前的動作,否則輸出當前模式空間的內容。造成的結果是連續多個空行,只有最后一個空行是保留輸出的,其余的都被刪除了。這樣的結果才是我們最初希望得到的。
三、打印行:P
P命令與p命令一樣是打印模式空間的內容,不同的是前者僅打印模式空間的第一行內容,而后者是打印所有的內容。因為編輯命令全部執行完之后,sed默認會輸出模式空間的內容,所以一般情況下,p和P命令都是與-n選項一起使用的。但是有一種情況是例外的,即編輯命令的執行流程被改變的情況,例如N,D等。很多情況下,P命令都是用在N命令之后,D命令之前的。這三個命令合起來,可以形成一人輸入輸出的循環,并且每次只打印一行:讀入一行后,N繼續讀下一行,P命令打印第一行,D命令刪除第一行,執行流程回到最開始重復該過程。
實例1:
[root@localhost?~]#?echo?-e?"line1nline2nline3"?|?sed?'$!N;P;D' line1nline2nline3 [root@localhost?~]#?echo?-e?"line1\nline2\nline3"?|?sed?'$!N;P;D' line1 line2 line3實例2:
[root@localhost?~]#?echo?-e?"line1\nline2\nline3"?|?sed?-n?'N;1P'說明:你可能期望打印第一行的內容,事實上并沒有輸出。原因是當N繼續讀入第二行后,當前行號已經是2了,行號只是sed在內部維護的一個計數變量而已,每當讀入新的一行,行號就加一。
實例3:
[root@localhost?~]#?echo?-e?"line1\nline2\nline3"?|?sed?-n?'$!N;=' 2 3實例4:N/P/D三個命令是如何配合使用
[root@localhost?~]#?cat?-n?f11??The?UNIX2??System?and?UNIX3??...[root@localhost?~]#?sed?'/UNIX$/{N;s/\nSystem/?Operating?&/;P;D}'?f1 The?UNIX?Operating? System?and?UNIX ...實例4執行流程圖:
轉載于:https://blog.51cto.com/yolynn/1890096
總結
以上是生活随笔為你收集整理的Linux高级文本处理之sed(三)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 根据IP地址查询其所属城市
- 下一篇: Linux内存管理和分析vmalloc使