SED之所以能以行為單位的編輯或修改文本,其原因在於它使用了兩個空間:一個是活動的“模式空間(pattern space)”,另一個是起輔助作用的“暫存緩沖區(holdingspace)這2個空間的使用。
sed編輯器逐行處理文件,並將輸出結果打印到屏幕上。sed命令將當前處理的行讀入模式空間(pattern space)進行處理,sed在該行上執行完所有命令后就將處理好的行打印到屏幕上(除非之前的命令刪除了該行),sed處理完一行就將其從模式空間中刪除,然后將下一行讀入模式空間,進行處理、顯示。處理完文件的最后一行,sed便結束運行。sed在臨時緩沖區(模式空間)對文件進行處理,所以不會修改原文件,除非顯示指明-i選項。
sed之所以能以行為單位的編輯或修改文本,其原因在於它使用了兩個空間:一個是活動的“模式空間(pattern space)”,另一個是起輔助作用的“保持空間(hold space)這2個空間的使用。
模式空間:可以想成工程里面的流水線,數據之間在它上面進行處理,用於處理文本行。
保持空間:可以想象成倉庫,我們在進行數據處理的時候,作為數據的暫存區域,用於保留文本行,是保存已經處理過的輸入行,默認有一個空行。
與模式空間和暫存空間(hold space)相關的命令:
n 輸出模式空間行,讀取下一行替換當前模式空間的行,執行下一條處理命令而非第一條命令。
N 讀入下一行,追加到模式空間行后面,此時模式空間有兩行。
h 把模式空間的內容復制到保留空間,覆蓋模式
H 把模式空間的內容追加到保留空間,追加模式
g 把保留空間的內容復制到模式空間,覆蓋模式
G 把保留空間的內容追加到模式空間,追加模式
x 將暫存空間的內容於模式空間里的當前行互換。
! 對所選行以外的所有行應用命令。
注意:暫存空間里默認存儲一個空行。
例子一
sed G
在文件每一行下面輸出一個空行
代碼: |
$ cat foo 11111111111111 22222222222222 33333333333333 44444444444444 55555555555555 $ sed G foo 11111111111111 22222222222222 33333333333333 44444444444444 55555555555555 |
解釋:
sed 中 G 的用法
The G function appends the contents of the holding area to the contents of the pattern space. The former and new contents are separated by a newline. The maximum number of addresses is two.
hold space : 保持空間(或者叫保留空間、緩沖區),初始為空
pattern space :模式空間
在上面的例子中,將為空的hold space附加到文件的每一行后面,所以結果是每一行后面多了一個空行
引申出:
sed '/^$/d;G'
在文件的每一個非空行下面輸出一個空行
sed '/^$/d;G;G'
在文件的每一個非空行下面輸出兩個空行
代碼: |
$ cat foo 11111111111111 22222222222222 33333333333333 44444444444444 55555555555555 $ sed '/^$/d;G' foo 11111111111111 22222222222222 33333333333333 44444444444444 55555555555555 |
注:有時會有一些由空格符或者TAB組成的空行,前面的正則式 ^$ 就不能匹配到這樣的行,則可以這樣
sed '/[[:space:]]/d;G'
例子二
sed '/regex/{x;p;x;}'
在匹配regex的所有行前面插入一個空行
代碼: |
$ cat foo 11111111111111 22222222222222 test33333333333333 44444444444444 55555555555555 $ sed '/test/{x;p;x;}' foo 11111111111111 22222222222222 test33333333333333 44444444444444 55555555555555 |
解釋:
sed 中 x 的用法
The exchange function interchanges the contents of the pattern space and the holding area. The maximum number of addresses is two.
即交換保持空間hold space和模式空間pattern space的內容
sed 中 p 的作用是把模式空間復制到標准輸出。
分析一下該命令執行過程中保持空間和模式空間的內容
命令 保持空間 模式空間
x 執行前:null 執行后:test\n 執行前:test\n 執行后:null
p 執行前:null 執行后:test\n 執行前:test\n 執行后:null 輸出一個空行
x 執行前:test\n 執行后:null 執行前:null 執行后:test\n
(注:把test所在的行簡寫為test了)
引申:
可以試驗一下 sed '/test/{x;p;}' foo 或者 sed '/test/{p;x;}' foo 等,看看結果,體會兩個空間的變化
相應的:
sed '/regex/G' 是在匹配regex的所有行下面輸出一個空行
sed '/regex/{x;p;x;G;}' 是在匹配regex的所有行前面和下面都輸出一個空行
例子三
sed 'n;G;'
在文件的偶數行下面插入一個空行
代碼: |
$ cat foo 11111111111111 22222222222222 33333333333333 44444444444444 55555555555555 $ sed 'n;G;' foo 11111111111111 22222222222222 33333333333333 44444444444444 55555555555555 |
解釋:
sed 中 n 的用法:將模式空間拷貝於標准輸出。用輸入的下一行替換模式空間。
執行 n 以后將第一行輸出到標准輸出以后,然后第二行進入模式空間,根據前面對 G 的解釋,會在第二行后面插入一個空行,然后輸出;再執行 n 將第三行輸出到標准輸出,然后第四行進入模式空間,並插入空行,依此類推
相應的:
sed 'n;n;G' 表示在文件的第 3,6,9,12,... 行后面插入一個空行
sed 'n;n;n;G' 表示在文件的第 4,8,12,16,... 行后面插入一個空行
sed 'n;d' 表示刪除文件的偶數行
例子四
sed '$!N;$!D'
輸出文件最后2行,相當於 tail -2 foo
代碼: |
$ cat foo 11111111111111 22222222222222 33333333333333 44444444444444 55555555555555 $ sed '$!N;$!D' foo 44444444444444 55555555555555 |
解釋:
D 刪除模式空間內第一個 newline 字母 \n 前的資料。
N 把輸入的下一行添加到模式空間中。
sed '$!N;$!D' : 對文件倒數第二行以前的行來說,N 將當前行的下一行放到模式空間中以后,D 就將模式空間的內容刪除了;到倒數第二行的時候,將最后一行附加到倒數第二行下面,然后最后一行不執行 D ,所以文件的最后兩行都保存下來了。
還有 N 的另外一種用法
代碼: |
$ sed = foo | sed N 1 11111111111111 2 22222222222222 3 33333333333333 4 44444444444444 5 55555555555555 $ sed = foo | sed 'N;s/\n/ /' 1 11111111111111 2 22222222222222 3 33333333333333 4 44444444444444 5 55555555555555 |
解釋:
N 的作用是加上行號,可以用於格式化輸出文件
例子五
sed '1!G;h;$!d'
sed -n '1!G;h;$p'
將文件的行反序顯示,相當於 tac 命令(有些平台沒有這個命令)
代碼: |
$ cat foo 11111111111111 22222222222222 33333333333333 $ sed '1!G;h;$!d' foo 33333333333333 22222222222222 11111111111111 $ sed -n '1!G;h;$p' foo 33333333333333 22222222222222 11111111111111 |
解釋:
sed 中 h 用法:h
The h (hold) function copies the contents of the pattern space into a holding area, destroying any previous contents of the holding area.
意思是將模式空間的內容保存到保持空間中去
sed 中的 d 表示刪除模式空間。
1!G表示除了第一行以外,其余行都執行G命令;$!d表示除了最后一行以外,其余行都執行d命令。
看一下sed '1!G;h;$!d'命令執行過程中保持空間與模式空間的變化:
命令 保持空間 模式空間
第一行 h;d 執行前:null 執行后:1111\n 執行前:1111\n 執行后:null
第二行 G;h;d 執行前:1111 執行后:2222\n1111\n 執行前:2222\n 執行后:null
第二行 G;h 執行前:2222\1111\n 執行后:3333\n2222\n\1111\n 執行前:3333\n 執行后:3333\n2222\n\1111\n
(注:把各個行簡寫了)
這樣輸出以后就是文件的反序了。
題外話:在vi中對一個文件進行反序顯示的命令是 :g/./m0 , 意思是按照文件正常順序每找到一行,就把該行放到文件的最上面一行去,這樣循環一下正好把文件的行反序顯示了。