fhc2007@fhc2007-desktop:~$ sed --help
用法: sed [選項]... {腳本(如果沒有其他腳本)} [輸入文件]...
-n, --quiet, --silent
取消自動打印模式空間
-e 腳本, --expression=腳本
添加“腳本”到程序的運行列表
-f 腳本文件, --file=腳本文件
添加“腳本文件”到程序的運行列表
-i[擴展名], --in-place[=擴展名]
直接修改文件(如果指定擴展名就備份文件)
-l N, --line-length=N
指定“l”命令的換行期望長度
--posix
關閉所有 GNU 擴展
-r, --regexp-extended
在腳本中使用擴展正則表達式
-s, --separate
將輸入文件視為各個獨立的文件而不是一個長的連續輸入
-u, --unbuffered
從輸入文件讀取最少的數據,更頻繁的刷新輸出
--help 打印幫助并退出
--version 輸出版本信息并退出
如果沒有 -e, --expression, -f 或 --file 選項,那么第一個非選項參數被視為
sed腳本。其他非選項參數被視為輸入文件,如果沒有輸入文件,那么程序將從標準輸入讀取數據。
ps: -n 參數和 -i 參數不要一起使用。
本章將以一節一個函數參數的方式 ,介紹所有 sed 提供的函數參數 , 其中有
|s|d|a|i|c|p|l|r|w|y|!|n|q|=|#|N|D|P|h|H|g|G|x|b|t|
另外 , 在各節中 , 首先簡單介紹函數參數功能 , 接著說明函數參數與位址參數配合的格式 ,而其中也一并描述 sed 執行此函數參數的工作情形。
s
函數參數 s 表示替換(substitute)文件內字串。其指令格式如下 :
[address1[ ,address2]] s/pattern/replacemen/[flag]
對上述格式有下面幾點說明 :
1、函數參數 s 最多與兩個位址參數配合。
2、關於 “s/pattern/replacement/[flag]” 有下面幾點說明:
3、范例:
數字標志很少使用,在這種情況下,正則表達式在一行上重復匹配,而只需對其中某個位置的匹配進行替換。例如,某輸入行也許包含 [tab](制表符)輸入,也許包含多個制表位。假設每行有3個制表符,并且要用“>”替換第二個制表位,則可以使用下面的替換命令來完成該功能:
s/[tab]/>/2
“[tab]“表示一個真正的制表符,而制表符在屏幕上是不可見的。如果輸入是一行的文件,如下所示:
Column1[tab]column2[tab]Column3[tab]Column4
對這個文件運行以上腳本產生的輸出如下:
Column1[tab]column2>Column3[tab]Column4
注意,如果沒有數字標志,則替換命令只替換第一個制表符(因此“1”可以被看作是默認的數字標志)。
我們可以對前面的示例做一些改動,用換行符取代每行上的第二個制表符。
s/[tab]/\
/2
注意,在反斜杠后面不允許有空格。這個腳本產生下面的結果:
Column1[tab]column2
Column3[tab]Column4
d
函數參數 d 表示刪除資料行 , 其指令格式如下:
[address1[ ,address2]] d
對上述格式有下面幾點說明:
- 函數參數 d 最多與兩個位址參數配合。
- sed 執行刪除動作情況如下 :
- 將 pattern space 內符合位址參數的資料刪除。
- 將下一筆資料讀進 pattern space 。
- 重新執行 sed script。
補遺:刪除命令是一個可以改變腳本中的控制流的命令。這是因為一旦執行這個命令,那么在“空的”模式空間(注:不允許在被刪除的行上進行進一步操作)中就不會再有命令執行。所以,刪除命令會導致讀取新的輸入行,而編輯腳本則從頭開始新的一輪。重要的是:如果某行匹配了模式中地址(地址參數),那么就刪除整個行,而不只是刪除行中匹配的部分(要刪除行的一部分,可以使用替換命令并指定一個空的替換)。
a
函數參數 a 表示將資料添加到文件中。其指令格式如下:
[address1] a\ 使用者所輸入的資料
對上述格式有下面幾點說明:
1、函數參數 a 最多與一個位址參數配合。
2、函數參數 a 緊接著 “\” 字元用來表示此行結束 , 使用者所輸入的資料必須從下一行輸入。如果資料超過一行 , 則須在每行的結尾加入”\”。
3、sed 執行添加動作情況如下 : 當 pattern space 內資料輸出後 , sed 跟著輸出使用者所輸入的資料。
4、范例 :
i
函數參數 i 表示將資料插入文件中。其指令格式如下:
[address1] i\ 使用者所輸入的資料
對上述格式有下面幾點說明:
1、函數參數 i 最多與一個位址參數配合。
2、函數參數 i 緊接著 “\” 字元用來表示此行結束 , 使用者所輸入的資料必須從下一行輸入。如果資料超過一行 , 則須在每行的結尾加入”\”。
3、sed 執行插入動作的情況如下 : 在 pattern space 內資料輸出前 , sed 先輸出使用者所輸入的資料。
4、范例 :
c
函數參數 c 表示改變文件中的資料。其格式如下:
[address1[ ,address2]]c\ 使用者所輸入的資料
對上述格式有下面幾點說明:
1、函數參數 c 最多與兩個位址參數配合。
2、函數參數 c 緊接著 “\” 字元用來表示此行結束 , 使用者所輸入的資料必須從下一行輸入。如果資料超過一行 , 則須在每行的結尾加入”\”。
3、sed 執行改變動作的情況 : 在 pattern space 內資料輸出時 , sed 改變它成為使用者所輸入的資料。
補遺:更改命令清除模式空間,它在空間模式中與刪除命令有同樣的效果。腳本中在更改命令之后的其他命令沒有被提供。
插入命令和追加命令不影響模式空間的內容。提供的文本將不匹配腳本中后續命令中的任何地址,那些命令也不影響該文本。不管什么更改改變了模式空間,所提供的文本仍然會正確輸出。當默認的輸出受到抑制時也是這樣——所提供的文本將被輸出,即時模式空間不是那樣的。而且,所提供的文本不影響 sed 的內部行計數器。
p
函數參數 p 表示印出模式空間中的資料。其指令格式如下 :
[address1[ , address2]] p
對於上述格式有下面幾點說明 :
1、函數參數 p 最多與兩個位址參數配合。
2、sed 執行印出動作的情況如下 : sed 拷備一份 pattern space 內容至標準輸出檔。
(除非抑制(-n)默認的輸出,否則打印命令將輸出行的重復復制。當抑制默認的輸出或者當通過程序的流程控制來避免到達腳本的底部時,可能會使用它。)
l
函數參數 l , 除可將模式空間資料中的 nonprinting character(非打印字符) 顯示為兩個數字的ASCII 代碼(GNU sed 顯示某些字符,例如,回車符,使用的是 ANSI C 轉義序列,而不是八進制。)外 , 其於均與函數參數 p相同。例如 , 將下面 input.dat 檔中的 ^[ 以 ASCII 碼印出
The Great ^[ is a movie starring Steve McQueen.
(在 vi 中的插入模式下通過鍵入 CTRL-V(大小寫無關),然后按下 ESC 鍵,產生字符 ^[ ,類似的,按下回車鍵可產生字符 ^M,按下 CTRL-A(大小寫無關),產生字符 ^A,其余類推。)
執行命令 sed -e 'l' input.dat 後 , 則輸出結果如下 :
The Great \033 is a movie starring Steve McQueen.
The Great is a movie starring Steve McQueen.
上述第二行資料為 sed 的自動輸出。
(在 sed 中不能用 ASCII 值匹配字符(也不能匹配八進制數值),所以,使用 sed 替換(或刪除)文檔中的非打印字符,得用 vi 來編輯 sed 的編輯命令腳本,使用命令腳本來執行 sed 而無法在命令行上輸入 sed 的命令參數。)
r
函數參數 r 表示讀入文件的內容到模式空間。其指令格式如下 :
[address1] r file
對於上述格式有下面幾點說明 :
1、函數參數 r 最多與一個位址參數配合。
2、在指令中 , 函數參數 r 與文件名稱間 , 必須有一空格(空格后到換行符前的每個字符都被當做文件名,因此,前導的和嵌入的空格也是文件名的一部分)。
3、sed 執行讀入動作的情況如下 : 在 pattern space 內資料輸出後 , sed 讀入由 file 指定的文件的內容跟著輸出。當 file 不存在時 ,sed 照樣執行其它指令而不會有任何錯誤訊息產生。
w
函數參數 w 表示將模式空間的內容寫入文件。其指令格式如下 :
[address1[ ,address2]] w file
對於上述格式有下面幾點說明 :
1、函數參數 w 最多與兩個位址參數配合。
2、在指令中 , 函數參數 w 與文件名稱間 , 必須有一空格(空格后到換行符前的每個字符都被當做文件名,因此,前導的和嵌入的空格也是文件名的一部分)。
3、sed 執行寫出動作的情況如 : 將 pattern space 內資料寫入文件 file。資料寫入時 , 會取代(overwrite)原來文件內的資料(如果一個腳本中有多個指令寫到同一個文件中,那么每個寫命令都將內容追加到這個文件中)。另外 , 當文件不存在時 , sed 會重新產生(creat)它。
y
函數參數 y 表示轉換資料中的字元。其指令格式如下 :
[address1[ ,address2]]y /xyz.../abc.../
對於上述格式有下面幾點說明 :
1、函數參數最多配合兩個位址參數。
2、指令中 , /abc.../xyz.../(x、y、z、a、b、c 代表某些字元) 為 y 的 argument 。其中 abc... 與xyz... 的字元個數必須相同。
3、sed 執行轉換時 , 將 pattern space 內資料內的 a 字元轉換成 x 字元 、b 字元轉換成 y 字元 、c 字元轉換成 z 字元 ...。
4、范例:
- 題目: 將 input.dat 檔中的小寫字母改成大寫。假設 input.dat 檔的內容如下 :
Sodd's Second Law:
Sooner or later, the worst possible set of
circumstances is bound to occur.
- 說明:利用函數參數 y 指示 sed 做字母大小的轉換。
- sed 命令列如下 :
sed -e '
y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
' input.dat
執行上述命令輸出結果如下 :
SODD'S SECOND LAW:
SOONER OR LATER, THE WORST POSSIBLE SET OF
CIRCUMSTANCES IS BOUND TO OCCUR.
!
函數參數 ! 表示不執行函數參數。當有如下指令時 ,
[address1[ , address2]] ! 函數參數
表示 , 對符合位址參數之資料不執行函數參數。例如刪除 , 除了含有 "regular" 字串的資料行外,所有資料行, 則執行 ! 后的刪除命令
sed -e '/regular/!d' input.dat
n
函數參數 n 表示讀入下一行資料。其指令格式如下:
[address1[ ,address2]] n
對上述格式有下面幾點說明 :
1、函數參數 n 最多配合兩個位址參數。
2、sed 執行讀入下一行動作的情況如下 :
- 輸出在 pattern space 的資料(默認輸出)。
- 將下一筆資料讀到 pattern space。
- 執行下一個編輯指令(不用返回到腳本的頂端)。
補遺:next 命令改變了正常的流控制(正常情況下,直到到達腳本的底部才會輸出模式空間的內容,總是在讀入新行之后從腳本的頂端開始)。實際上,next 命令導致輸入的下一行取代模式空間中的當前行。腳本中的后續命令應用于替換后的行,而不是當前行。如果沒有抑制默認輸出,那么在替換發生之前會打印當前行。在較長的腳本中,必須記住出現在 next 命令之前的命令不會應用于新的輸入行,而出現在其后面的命令不應用于舊的輸入行。
3、范例
q
函數參數 q 表示跳離 sed 。其指令格式如下:
[address1] q
對上述格式有下面幾點說明 :
1、函數參數 q 最多配合一個位址參數。
2、sed 執行跳離動作時 , 它停止讀取新的輸入行(并停止將它們發送到輸出)。
(退出命令 q 只適用于單行的地址。一旦找到和 address 匹配的行,那么腳本就結束。注:需要小心的是,在將編輯操作寫回到原始文件的任何程序中不要使用 q 命令。在執行 q 命令之后,就不會再產生輸出。在想要編輯文件的一部分并保留剩余部分不改變的情況下,不要使用 q 命令。這種情況下使用 q 時初學者常犯的非常危險的錯誤。)
示例,下面一行命令使用退出命令從文件中打印前100行:
$ sed '100q' test
...
它打印每一行,直到它到達行100并且退出。在這點上,這個命令的功能與 UNIX 的 head 命令類似。
quit 的另一個可能的用法是從文件中提取了想要的內容后退出腳本。
3、范例 :
=
函數參數 = 表示印出資料的行號。其指令格式如下:
[address1[ ,address2]] =
對上述格式有下面幾點說明 :
1、函數參數 = 最多配合兩個位址參數。
2、執行時 , 行號將在資料輸出前先輸出。
3、范例 :
#
在 script file 內 , 函數參數 # 後的文字為注解。當注解文字超過多行時 , 其行間須以 "\" 換行字元相隔。在 sed 的System V版本中,注釋只允許出現在第一行。而 GNU sed 則可以在腳本的任何地方放置注釋,甚至是跟在命令行的后面。注釋行的第一個字符必須是“#”號。如果跟在#后面的下一個字符是 n,那么腳本不會自動產生輸出。這和指定命令行選項 -n 是等價的。跟在 n 后面的其余內容被看做是注釋。在POSIX標準中,采用這種方式的 #n 必須是文件的前兩個字符。
到此為止,前面介紹的命令(函數參數)可歸類為基本的 sed 命令,下面將要介紹的這些命令可歸類為 sed 的高級命令。sed 的高級命令可分成3個組:
1、處理多行模式空間(N、D、P)。
2、采用保持空間來保存模式空間的內容并使它可用于后續的命令(H、h、G、g、x)。
3、編寫使用分支和條件指令的腳本來更改控制流(:、b、t)。
多行模式空間
在前面的正則表達式討論中,我們強調模式匹配是面向行的。像 grep 這樣的程序嘗試在單個輸入行上匹配一個模式。這就使它很難匹配一個在一行的結尾處開始,并在下一行的開始處結束的短語。其他一些模式只有當在多行上匹配才有意義。
sed 能查看模式空間的多個行。這就允許匹配模式擴展到多行上。下面我們將要介紹創建多行模式空間并處理它的內容的命令。這里的 3 個多行命令(N、D、P)對應于前面介紹的小寫字母的基本命令(n、d、p)。
N
函數參數 N 表示添加下一筆資料在 pattern space 內。其指令格式如下:
[address1[ ,address2]] N
對上述格式有下面幾點說明 :
1、函數參數 N 最多配合兩個位址參數。
2、sed 執行時 , 將下一行資料讀入并添加在 pattern space 內 , 資料行間以換行字元(embedded newline character)分隔。此外 , 在替換時 , 換行字元可用轉義序列 \n 來匹配。
在多行模式空間中,元字符“^”匹配模式空間中的第一個字符,而不匹配換行符后面的字符。同樣,“$”只匹配模式空間中最后的換行符,而不匹配任何嵌入的換行符。在執行 Next 命令之后,控制將被傳遞給腳本中的后續命令(同 next )。Next 命令與 next 命令不同,next 輸出模式空間的內容,然后讀取新的輸入行。next 命令不創建多行模式空間。
3、范例 :
- 題目: 將下述兩行資料合。假設 input.dat 的內容如下 :
The UNIX
Operating System
- 說明 : 先利用函數參數 N 將兩行資料置於 pattern space 內 , 在利用函數參數 s/\n/ / 將兩行資料間的分隔符 \n 以空白替代 , 如此兩行資料變成一行輸出。
- sed 命令列如下 :
sed -e 'N' -e 's/\n/ /' input.dat
執行上述命令後 , 其輸出的結果如下:
The UNIX Operating System
D
函數參數 D 表示刪除 pattern space 內的第一行資料(刪除模式空間中直到第一個嵌入的換行符的這部分內容)。其指令格式如下:
[address1[ ,address2]]D
對上述格式有下面幾點說明 :
1、函數參數 D 最多配合兩個位址參數。
2、函數參數 D 與 d 的比較如下 :
- 當 pattern space 內只有一資料行時 , D 與 d 作用相同。
- 當 pattern space 內有多行資料行時
- D 表示只刪除 pattern space 內第一行資料 ; d 則全刪除。
- D 表示執行刪除后 , pattern space 內不添加下一筆資料 , 而將剩下的資料重新執行 sed script (返回到腳本的頂端,將這些指令應用于模式空間剩余的內容);d 則讀入下一行后重新執行 sed script(返回到腳本的頂端)。
P
函數參數 P 表示印出 pattern space 內的第一行資料(輸出多行模式空間的第一部分,直到第一個嵌入的換行符為止)。其指令格式如下:
[address1[ ,address2]] P
對上述格式有下面幾點說明 :
1、函數參數 P 最多配合兩個位址參數。
2、P 與 p , 除了面對的 pattern space 內的資料行數不同外 , 其它均相同。
在執行完腳本的最后一個命令之后,模式空間的內容自動輸出(-n 選項或 #n 抑制這個默認的動作)。因此當默認的輸出被抑制或者腳本中的控制流更改,以至不能達到腳本的底部時,需要使用打印命令(P 或 p)。Print 命令經常出現在 Next 命令之后和 Delete 命令之前。這 3 個命令能建立一個輸入/輸出循環,用來維護兩行的模式空間,但是一次只輸出一行。這個循環的目的是只輸出模式空間的第一行,然后返回到腳本的頂端將所有的命令應用于模式空間的第二行。沒有這個循環,當執行腳本中的最后一個命令時,模式空間中的這兩行都被輸出。
3、范例:
- 題目 : 輸出 input.dat 檔內奇數行資料。假設 input.dat 檔內容如下:
The
UNIX
System
- 說明: 在命令列上
- 以選項 -n , 將資料輸出的控制權轉給指令。
- 利用函數參數 N 將偶數行添加至 pattern space 內奇數行後。
- 利用函數參數 P 將 pattern space 內的第一行(奇數行)輸出。
在奇數行輸出後 , pattern space 內剩下的資料行(偶數行)則被放棄輸出。最後 , 整個輸出只有原先的奇數行資料。
- sed 命令列 :
sed -n -e 'N' -e 'P' input.dat
執行上述命令後 , 輸出的結果如下 :
The
System
模式空間與保持空間
模式空間的內容可以復制到保持空間,而且保持空間的內容也可以復制到模式空間。有一組命令用于在保持空間和模式空間之間移動數據。保持空間用于臨時存儲。單獨的命令不能尋址保持空間或者更改它的內容。
保持空間最常見的用途是,當改變模式空間中的原始內容時,用于保留當前輸入行的副本。影響模式空間的命令有:
命令 縮寫 功能
Hold h 或 H 將模式空間的內容復制或追加到保持空間
Get g 或 G 將保持空間的內容復制或追加到模式空間
Exchang x 交換模式空間和保持空間的內容
hold(h,H)命令將數據移至保持空間,而 get(g,G)命令將保持空間的數據移回到模式空間。同一命令的小寫字母和大寫字母之間的差別是,小寫字母命令改寫目的緩存區的內容,而大寫字母命令追加緩存區的現有內容。
hold(小寫)命令用模式空間的內容取代保持空間的內容。get(小寫) 命令用保持空間的內容取代模式空間的內容。
Hold(大寫)命令在保持空間的內容之后放置一個換行符,且后面跟隨模式空間的內容(即使保持空間是空的,換行符也被追加到保持空間)。Get(大寫)命令在模式空間的內容之后放置一個換行符,且后面跟隨保持空間的內容。
交換命令交換兩個緩存區的內容。對兩個緩存區沒有副作用。
h
函數參數 h 表示暫存 pattern space 的資料至 hold space。其指令格式如下:
[address1[ ,address2]] h
對上述格式有下面幾點說明 :
1、函數參數 h 最多配合兩個位址參數。
2、sed 執行暫存動作時 , 會蓋掉(overwrite) hold space 內原來的資料。
3、當 sed 全部執行結束時 , hold space 內資料會自動清除。
H
函數參數 H 與 h 唯一差別是 , sed 執行 h 時 , 資料蓋掉(overwrite) hold space 內原來的資料 ,而 H , 資料則是 "添加(append)" 在 hold space 原來資料後。
g
函數參數 g 表示與函數參數 h 相反的動作 , 它表示將 hold space 內資料放回 pattern space內。其指令格式如下 :
[address1[ ,address2]]g
函數參數 g 最多配合兩個位址參數。
sed 執行放回動作時 , 資料蓋掉(overwrite) pattern space 內原來的資料。
G
函數參數 G 與 g 唯一差別是 , sed 執行 g 時 , 資料蓋掉(overwrite) pattern space 內原來的資料 , 而 G , 資料則是 "添加(append)" 在 pattern space 原來資料後。
x
函數參數 x 表示交換 hold space 與 pattern space 內的資料。其指令格式如下 :
[address1[ ,address2]] x
函數參數 x 大部份與其它處理 hold space 的函數參數一起配合。例如 , 將 input.dat 檔內第 1 行資料取代第 3 行資料。此時 , 用函數參數 h 與 x 來配合。其中 , 以函數參數 h 將第 1 資料存入 hold space ;當第 3 行資料出現在pattern space , 以函數參數 x 交換 hold space 與 pattern space 的內容。如此 , 第 3 行資料就被第 1 資料替代。其命令列如下:
sed -e '1h' -e '3x' input.dat
高級流程控制指令
分支(b)和測試(t)命令將腳本中的控制轉移到包含特殊標簽的行。如果沒有指定標簽,則將控制轉移到腳本的結尾處。分支命令用于無條件轉移,測試命令用于有條件轉移,它們只有當替換命令改變當前行時才會執行。
標簽是任意不多于7個字符的序列(GNU sed 允許標簽為任意長度)。標簽本身占據一行并以冒號開始:
:mylabel
在冒號和標簽之間不允許有空格。行結尾處的空格將被認為是標簽的一部分。當在分支命令或測試命令中指定標簽時,在命令和標簽之間允許有空格:
b mylabel
注意,不要在標簽后面插入空格。
b、:label
函數參數 : 與函數參數 b 可在 sed script 內建立類似 BASIC 語言中 GOTO 指令的功能。其中 , 函數參數 : 建立標記;函數參數 b 將下一個執行的指令 branch 到標記處執行。函數參數 : 與 b , 在 script file 內配合的情況如下
.
.
.
編輯指令m1
:記號
編輯指令m2
.
.
.
[address1[ ,address2]]b [記號]
其中 , 當 sed 執行至指令 [address1[ ,address2]]b [記號] 時 , 如 pattern space 內的資料符合位址參數 , 則 sed 將下一個執行的位置 branch 至由 :記號設定的標記處 , 也就是再由 "編輯指令 m2" ... 執行。另外 , 如果指令中函數參數 b 後沒有記號 , 則 sed 將下一個執行的指令 branch 到 script file 的最後 , 利用此可使 sed script 內有類似 C 語言中的 case statement 結構。
范例 :
t
基本上 , 函數參數 t 與 函數參數 b 的功能類似 , 除了在執行 t 的 branch 前 , 會先去測試其前的替換指令有沒有執行替換成功外。在 script file 內的情況如下:
.
.
.
編輯指令m1
:記號
編輯指令m2
.
.
.
s/.../.../
[address1[ ,address2]]t [記號]
編輯指令m3
其中 , 與函數參數 b 不同處在於 , 執行函數參數 t branch 時 , 會先檢查其前一個替換指令成功與否。如成功 , 則執行 branch ; 不成功 , 則不 branch , 而繼續執行下一個編輯指令 , 例如上面的編輯指令m3。
范例: