Linux -- sed命令(4)

2 多行刪除命令
單行刪除命令d用來刪除模式空間中的當前行。但和 N 命令一起使用時,使用單行刪除命令就要小心了。

$ sed ‘N ; /System\nAdministrator/d’ data4.txt
All System Administrators should attend.
刪除命令會在不同的行中查找單詞System和Administrator,然後在模式空間中將兩行都刪掉。這未必是你想要的結果。

sed編輯器提供了多行刪除命令D,它只刪除模式空間中的第一行。該命令會刪除到換行符(含
換行符)爲止的所有字符。

$ sed ‘N ; /System\nAdministrator/D’ data4.txt
Administrator’s group meeting will be held.
All System Administrators should attend.
文本的第二行被 N 命令加到了模式空間,但仍然完好。如果需要刪掉目標數據字符串所在行的前一文本行,它能派得上用場。

這裏有個例子,它會刪除數據流中出現在第一行前的空白行。

$ cat data5.txt

This is the header line.
This is a data line.
This is the last line.
$ sed ‘/^$/{N ; /header/D}’ data5.txt
This is the header line.
This is a data line.
This is the last line.
sed編輯器腳本會查找空白行,然後用 N 命令來將下一文本行添加到模式空間。如果新的模式空間內容含有單詞header,則 D 命令會刪除模式空間中的第一行。如果不結合使用N命令和D命令,就不可能在不刪除其他空白行的情況下只刪除第一個空白行。

  1. 多行打印命令
    現在,你可能已經瞭解了單行和多行版本命令間的差異。多行打印命令P沿用了同樣的方法,它只打印多行模式空間中的第一行。這包括模式空間中直到換行符爲止的所有字符。當你用-n選項來阻止腳本輸出時,它和顯示文本的單行p命令的用法大同小異。

$ sed -n ‘N ; /System\nAdministrator/P’ data3.txt
On Tuesday, the Linux System
當多行匹配出現時,P命令只會打印模式空間中的第一行。多行P命令的強大之處在和N命令
及D命令組合使用時才能顯現出來。

D命令的獨特之處在於強制sed編輯器返回到腳本的起始處,對同一模式空間中的內容重新執行這些命令(它不會從數據流中讀取新的文本行)。在命令腳本中加入N命令,你就能單步掃過整個模式空間,將多行一起匹配。

使用P命令打印出第一行,然後用D命令刪除第一行並繞回到腳本的起始處。一旦返
回,N命令會讀取下一行文本並重新開始這個過程。這個循環會一直繼續下去,直到數據流結束。

四、保持空間
模式空間(pattern space)是一塊活躍的緩衝區,在sed編輯器執行命令時它會保存待檢查的文本。但它並不是sed編輯器保存文本的唯一空間。

sed編輯器有另一塊稱作保持空間(hold space)的緩衝區域。在處理模式空間中的某些行時,可以用保持空間來臨時保存一些行。有5條命令可用來操作保持空間。

表1 sed編輯器的保持空間命令

命 令 描 述
h 將模式空間複製到保持空間
H 將模式空間附加到保持空間
g 將保持空間複製到模式空間
G 將保持空間附加到模式空間
x 交換模式空間和保持空間的內容
這些命令用來將文本從模式空間複製到保持空間。這可以清空模式空間來加載其他要處理的字符串。

通常,在使用 h 或 H 命令將字符串移動到保持空間後,最終還要用 g 、 G 或 x 命令將保存的字符串移回模式空間(否則,你就不用在一開始考慮保存它們了)。由於有兩個緩衝區域,弄明白哪行文本在哪個緩衝區域有時會比較麻煩。這裏有個簡短的例子演示瞭如何用 h 和 g 命令來將數據在sed編輯器緩衝空間之間移動。

sed -n ‘/first/ {h ; p ; n ; p ; g ; p }’ data2.txt
This is the first data line.
This is the second data line.
This is the first data line.

我們來一步一步看上面這個代碼例子:
(1) sed腳本在地址中用正則表達式來過濾出含有單詞first的行;
(2) 當含有單詞first的行出現時,h命令將該行放到保持空間;
(3) p命令打印模式空間也就是第一個數據行的內容;
(4) n命令提取數據流中的下一行( This is the second data line ),並將它放到模式
空間;
(5) p命令打印模式空間的內容,現在是第二個數據行;
(6) g命令將保持空間的內容( This is the first data line )放回模式空間,替換當
前文本;
(7) p命令打印模式空間的當前內容,現在變回第一個數據行了。

通過使用保持空間來回移動文本行,你可以強制輸出中第一個數據行出現在第二個數據行後面。如果丟掉了第一個 p 命令,你可以以相反的順序輸出這兩行。

​```shell
$ sed -n ‘/first/ {h ; n ; p ; g ; p }’ data2.txt
This is the second data line.
This is the first data line.
這是個有用的開端。你可以用這種方法來創建一個sed腳本將整個文件的文本行反轉!但要那麼做的話,你需要了解sed編輯器的排除特性,也就是下節的內容。

五、排除命令
排除命令用於配置命令使其不要作用到數據流中的特定地址或地址區間。感嘆號命令!用來排除( negate )命令,也就是讓原本會起作用的命令不起作用。下面的例子演示了這一特性。

$ sed -n ‘/header/!p’ data2.txt
This is the first data line.
This is the second data line.
This is the last line.
普通p命令只打印data2文件中包含單詞header的那行。加了感嘆號之後,情況就相反了:除了包含單詞header那一行外,文件中其他所有的行都被打印出來了。

感嘆號在有些應用中用起來很方便。之前遇到的一種情況:sed編輯器無法處理數據流中最後一行文本,因爲之後再沒有其他行了。可以用感嘆號來解決這個問題。

$ sed 'N;

s/System\nAdministrator/Desktop\nUser/
s/System Administrator/Desktop User/
’ data4.txt
On Tuesday, the Linux Desktop
User’s group meeting will be held.
All System Administrators should attend.
$ sed '$!N;
s/System\nAdministrator/Desktop\nUser/
s/System Administrator/Desktop User/
’ data4.txt
On Tuesday, the Linux Desktop
User’s group meeting will be held.
All Desktop Users should attend.
這個例子演示瞭如何配合使用感嘆號與 N 命令以及與美元符特殊地址。美元符表示數據流中的最後一行文本,所以當sed編輯器到了最後一行時,它沒有執行 N 命令,但它對所有其他行都執
行了這個命令。

使用這種方法,你可以反轉數據流中文本行的順序。要實現這個效果(先顯示最後一行,最
後顯示第一行),你得利用保持空間做一些特別的鋪墊工作。

你得像這樣使用模式空間:

(1) 在模式空間中放置一行;
(2) 將模式空間中的行放到保持空間中;
(3) 在模式空間中放入下一行;
(4) 將保持空間附加到模式空間後;
(5) 將模式空間中的所有內容都放到保持空間中;
(6)重複執行第(3)~(5)步,直到所有行都反序放到了保持空間中;
(7) 提取並打印行。
圖21-1詳細描述了這個過程。
在使用這種方法時,你不想在處理時打印行。這意味着要使用 sed 的 -n 命令行選項。下一步
是決定如何將保持空間文本附加到模式空間文本後面。這可以用 G 命令完成。唯一的問題是你不
想將保持空間附加到要處理的第一行文本後面。這可以用感嘆號命令輕鬆解決:
1!G
下一步就是將新的模式空間(含有已反轉的行)放到保持空間。這也非常簡單,只要用 h 命
令就行。
將模式空間中的整個數據流都反轉了之後,你要做的就是打印結果。當到達數據流中的最後
一行時,你就知道已經得到了模式空間的整個數據流。打印結果要用下面的命令:
$p
這些都是你創建可以反轉行的sed編輯器腳本所需的操作步驟。現在可以運行一下試試:

$ cat data2.txt
This is the header line.
This is the first data line.
This is the second data line.
This is the last line.
$ sed -n ‘{1!G ; h ; $p }’ data2.txt
This is the last line.
This is the second data line.
This is the first data line.
This is the header line.
sed編輯器腳本的執行和預期的一樣。腳本輸出反轉了文本文件中原來的行。這展示了在sed
腳本中使用保持空間的強大之處。它提供了一種在腳本輸出中控制行順序的簡單辦法。

有個Linux命令已經有反轉文本文件的功能了。 tac 命令會倒序顯示一個文本文件。這個命令的名字很巧妙,它執行的正好是與 cat 命令相反的功能。

六、分支命令
前面瞭解到可以使用!來排除不想要操作的行,但如果要對這些行進行其他的操作時就要用到分支命令了.

分支( branch )命令 b 的格式如下:

[ address ]b [ label ]

address 參數決定了哪些行的數據會觸發分支命令。 label 參數定義了要跳轉到的位置。你可以定義多種label對不同類的行進行不同的操作。

$ sed '{/2/b jump1; /3/b jump2; s/test/No jump/

:jump1 s/test/Jump1 here/
:jump2 s/test/Jump2 here/}’ test
No jump 1
Jump1 here 2
Jump2 here 3
No jump 4
滿足標籤12的,執行s/test/Jump1 here/命令;滿足標籤23的,執行s/test/Jump2 here/命令;其他的執行s/test/No jump/命令。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章