天天看點

sed 進階

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".      

替代單獨的單詞

在腳本中使用 sed

使用包裝腳本

重定向 sed 的輸出

建立 sed 實用工具

加倍行間距

對可能含有空白行的檔案加倍行間距

給檔案中的行編号

列印末尾行

删除行

删除HTML标簽