contents
- 多行指令
- next 指令
- 單行的next指令
- 合并文本行
- 多行删除指令
- 多行列印指令
- 保持空間
- 排除指令
- 改變流
- 分支
- 測試
- 模式替換
- &符号
- 替代單獨的單詞
- 在腳本中使用 sed
- 使用包裝腳本
- 重定向 sed 的輸出
- 建立 sed 實用工具
- 加倍行間距
- 對可能含有空白行的檔案加倍行間距
- 給檔案中的行編号
- 列印末尾行
- 删除行
- 删除HTML标簽
多行指令
在sed編輯器讀取資料流時,它會基于換行符的位置将資料分成行。sed編輯器根據定義好的腳本指令一次處理一行資料,然後移到下一行重複這個過程。
如果你在文本資料中查找某個短語時,他有可能被分隔成跨行顯示,如果用普通的sed編輯器指令來處理文本,就不可能發現這種被分開的短語。
sed編輯器包含了三個可用來處理多行文本的特殊指令:
- N:将資料流中的下一行加進來建立一個多行組來處理。
- D:删除多行組中的一行。
- P:列印多行組中的一行。
next 指令
單行的next指令
通常sed編輯器在移動到資料流中的下一行文本前,會在目前行上執行完所有定義好的命名。而next指令,會告訴sed編輯器移動到資料流中的下一行文本,而不是重新執行指令。
sed '/header/{n ; d}' data.txt
腳本查找含有單詞header的那一行,找到後,n指令會讓sed編輯器移動到文本的下一行,sed編輯器會繼續執行指令清單,該指令清單使用d指令來删除空白行,sed編輯器執行完指令腳本後,會從資料流中讀取下一行文本,并從頭開始執行指令腳本。
合并文本行
單行next指令會将資料流中的下一文本行移動到sed編輯器的工作空間。多行版本的next指令(N)會将下一文本行添加到模式空間中已有的文本後。
這樣的作用是将資料流中的兩個文本行合并到統一模式空間中。文本行仍然用換行符分隔,但sed編輯器現在會将兩行文本當成一行來處理。
sed '/first/{ N ; s/\n/ / }' data.txt
sed 編輯器腳本查找含有單詞first的那行文本,找到該行後,它會用N指令将下一行合并到那行,然後用替換指令s将換行符替換成空格。
多行删除指令
和N指令一起使用時,使用單行删除指令就要小心了。
sed 'N ; /System\nAdministrator/d' data.txt
删除指令會在不同行中查找單詞System和Administrator,然後再模式空間中将兩行都删掉。這未必是你想要的結果。
sed編輯器提供了多行删除指令D,它隻删除模式空間中的第一行,該指令會删除到換行符(含換行符)為止的所有字元。
sed 'N ; /System\nAdministrator/D' data.txt
sed '/^$/{N ; /header/D}' data.txt
sed 編輯器腳本會查找空白行,然後用N指令來将下一文本行添加到模式空間。如果新的模式空間内容含有單詞header,則D指令會删除模式空間中的第一行。如果不結合使用N指令和D指令,就不能再不删除其他空白行的情況下隻删除第一個空白行。
多行列印指令
現在,你可能已經了解了單行和多行版本指令的差異,多行列印指令(P)沿用了同樣的方法。它隻列印多行模式空間中的第一行。這包括模式空間中直到換行符為止的所有字元。
D指令的獨特之處在于強制sed編輯器傳回到腳本的起始處,對同一模式空間中的内容重新執行這些指令。在指令腳本中加入N指令,你就能單步掃過整個模式空間,将多行一起比對。
使用P指令列印出第一行,然後用D指令删除第一行并繞回到腳本的起始處。一旦傳回,N指令會讀取下一行文本并重新開始這個過程。這個循環會一直繼續下去,直到資料流結束。
保持空間
模式空間是一塊活躍的緩沖區,在sed編輯器執行指令時它會儲存待檢查的文本。但它并不是sed編輯器儲存文本的唯一空間。
sed編輯器有另一塊稱作保持空間的緩沖區域,在處理模式空間中的某些行時,可以用保持空間來臨時儲存一些行。
保持空間指令:
指令 | 描述 |
h | 将模式空間複制到保持空間 |
H | 将模式空間附加到保持空間 |
g | 将保持空間複制到模式空間 |
G | 将保持空間附加到模式空間 |
x | 交換模式空間和保持空間的内容 |
通常,在使用h或H指令将字元串移動到保持空間後,最終還要用g、G或x指令将儲存的字元串移回模式空間。
(未完待續…)
排除指令
你可以配置指令使其不要作用到資料流中的特定位址或位址空間。
感歎号指令用來排除指令,讓原本會起作用的指令不起作用。
sed -n '/header/!p' data.txt
除了包含單詞header那一行外,檔案中其他所有的行都被列印出來了。
(未完待續…)
改變流
通常sed編輯器會從腳本的頂部開始,一直執行到腳本的結尾(D指令是個例外,它會強制sed編輯器傳回到腳本的頂部,而不讀取新的行)
分支
sed 編輯器提供了一種方法,可以基于位址、位址模式或位址區間排除一整塊指令。
[addres]b [label]
address 參數決定了哪些行的資料會觸發分支指令。label 參數定義了要跳轉到的位置,如果沒有加入label參數,跳轉指令會跳到腳本的結尾。
sed '{2,3b; s/This is/Is this/ ; s/line./test?/}' data.txt
分支指令在資料流中的第2行和第3行處跳過了兩個替換指令。
要是不想直接跳到腳本的結尾,可以為分支指令定義一個要跳轉的标簽,标簽以冒号開始,最多可以是7個字元長度。
(未完待續…)
測試
測試指令(t)也可以用來改變sed編輯器腳本的執行流程,測試指令會根據替換指令的結果跳轉到某個标簽,而不是根據位址進行跳轉。
[address]t [label]
跟分支指令一樣,在沒有指定标簽的清空下,如果測試成功,sed會跳轉到腳本的結尾。如果已經做了一個替換,不需要再做另一個替換,那麼測試指令能幫上忙。
sed '{
s/first/matched/
t
s/This is the/No match on/
}' data.txt
第一個替換指令會查找模式文本first,如果比對了行中的模式,它就會替換文本,而且測試指令會跳過後面的替換指令,如果第一個替換指令未能比對模式,第二個替換指令就會被執行。
當無需替換時,測試指令不會跳轉而是繼續執行剩下的腳本。
模式替換
如果你隻是要比對模式中的一個單詞:
$ echo "The cat sleeps in his hat." | sed 's/cat/"cat"/'
The "cat" sleeps in his hat.
但是如果你在模式中用通配符來比對多個單詞呢?
$ echo "The cat sleeps in his hat." | sed 's/.at/"".at"/g'
The ".at" sleeps in his ".at".
用于替代的字元串無法比對已比對單詞中的通配符字元。
&符号
$ echo "The cat sleeps in his hat." | sed 's/.at/"&"/g'
The "cat" sleeps in his "hat".