sed指令
在腳本中應用指令:
替換指令
s/pig/cow/g
s/cow/horse/g
模式空間
sed維護一種模式空間,即一個工作區或者臨時緩沖區,當應用編輯指令時,将在那裡存儲單個輸入行。
注意:一次一行的設計的一個優點是sed在讀取非常大的檔案時不會出現問題。螢幕編輯程式必須将整個檔案讀入記憶體,這将會産生記憶體溢出或者在處理龐大的檔案時速度非常慢。
尋址上的全局透視
sed是隐式全局的,例如下面的替換指令,将每個"CA"替換成"California"
s/CA/Californai/g
我們也可以限制隻對包含"Sebastopol"的行才将"CA"替換為"California"
Sebastopol/s/CA/California/g
由“Sebastopol”“CA”組成的輸入行将比對這個位址,并且應用替換指令将他替換為“Sebastopol”“California”. 右“San Fracicso”“CA”組成的行不會被比對,而且不會應用替換指令。
sed指令可以指定零個、一個或兩個位址。每個位址都是一個描述模式。行号或者行尋址符号的正規表達式。
注意:
1、如果沒有指定位址,那麼指令将應用于每一行。
2、如果隻有一個位址,那麼指令應用于與這個位址比對的任意行。
3、如果指定了由逗号分隔的兩個位址,那麼指令應用于比對第一個位址的第一行,和他後面的行,直到比對第二個位址的行。
4、如果位址後面跟有感歎号(!),那麼指令就應用于不比對該位址的所有行。
删除指令d
1.一個隻有d指令組成,并且沒有位址的腳本不會産生輸出,因為它删除了所有的行。
2.當行号作為一個位址提供時,指令隻影響那一行,例如:1d ,删除最後一行,使用$d。
3.當正規表達式作為位址提供時,這個指令隻影響與這個模式比對的行。正規表達式必須封閉在(/)中,下面的删除指令為"/^$/d" :隻删除空行。
4.如果提供了兩個位址,那麼就指定了指令執行的行範圍。下面展示了如何删除由一對宏包圍的所有行,在這種情況下,.TS和.TE标記了tb1的輸入:/^\.TS/,/^.TE/d
注意:它删除了從第一種模式比對的行開始,到由第二種模式比對的行(包括此行在内)為止的所有的行這個範圍的行不受影響。
5.下面的指令删除了檔案中從行50到最後一行的所有行:50,$d
可以混合使用行位址和模式位址:1,/^$/d 這個示例删除了從第一行直到第一個空行的所有的行,例如,可以用他來删除儲存在檔案中的Internet郵件消息中的郵件頭。
注意:1.可以把第一個位址看做是啟用位址,并把第二個位址看成是禁用動作,sed沒有辦法先行決定第二個位址是否會比對。一旦比對了第一個位址,這個動作就将應用于這些行。于是指令應用于“所有”随後的行,直到第二個位址被比對。,在上例中,如果檔案不包含空行,那麼将删除所有的行。
2.跟在位址後面的感歎号會反轉比對的意義。例如,下面的腳本将删除在tb1輸入塊中的那些行以外的所有行。/^\.TS/,/^.TE/!d
指令分組
1.sed使用大括号({})将一個位址嵌入在另一個位址中,或者在相同的位址上應用多個指令。如果想指定行的範圍,然後在這個範圍内指定另一個位址,則可以嵌套位址。例如:為了隻删除tb1輸入塊中的空行,使用下面的指令:/^\.TS/,/^\.TE/{
/^$/d
}
注意:左大括号必須在行末,而且右大括号本身必須單獨占一行,并且確定在大括号之後沒有空格。
2.可以使用大括号将編輯指令括起來對某個範圍的行應用多個指令,如下所示:
/^\.TS/,/^\.TE/{
s/^\.ps 10/.ps 8/
s/^\.vs 12/.vs 10/
注意:這個示例不僅删除了tb1輸入塊中的空行,而且他還使用了替換指令s,改變了幾個troff的請求,這些指令隻應用于.TS/.TE塊中的行。
測試并儲存輸出
在前面關于模式空間的讨論中,可以看到sed:
生成輸入行的備份
修改模式空間中的備份
将備份輸出到标準輸出
這些都意味着sed有其内置的安全措施,是以會改變原始的檔案。是以,下面的指令行:
sed -f sedscr testfile:不會在testfile中做改動。它将所有的行送往标準輸出(一般指螢幕),----包括被修改的行和沒有被修改的行。如果想要儲存這些輸出,就必須将他們輸入到一個新的檔案中。
sed -f sedscr testfile > newfile 其中,重定向符号">"将來自sed的輸出直接送往檔案newfile中。不要将來自指令的輸出重定向到輸入檔案,否則會改寫輸入檔案,甚至可能在sed處理這個檔案之前,并破壞你的資料。
檢查newfile和testfile檔案的差别:
diff testfile newfile
sed腳本的四種類型
1.對同一檔案的多重編輯:sed腳本的第一種類型示範了在一個檔案中進行一系列程式設計工作。我們使用的第一個示例是将由字處理程式建立的檔案轉換為用于troff的編碼檔案。
下面是Horsefeathers Software 産品說明顯然需要做的一個編輯工作的清單:
a.用段落宏(.LP)取代所有的空行。要求是比對空行,但是,在檢視輸入檔案内容時,空行是否有前導空格并不明顯。當清楚空格後,它們沒有前導空格,是以空行可以采用模式“^$”來比對。(如果行上有空格,那麼模式寫成“^[]*$*”)。是以,可以用以下的方法簡單的實作:
[root@localhost sed]# cat horse.txt
HORSEFEATHERS SOFTWARE PRODUCT BULLETIN DESCRIPTION
+ _______________
BigOne Computer offers three software packages from the suite of Horsefeather software products -- Horsefeathers Business BASIC Librarian, and LIDO. These software products can fill your
requirements for powerful ,sophisticated, general-purpose business software providing you with a base for software customization or development.
Horsefeathers BASIC is BASIC optimized for use on the BigOne machine with UNIX or MS-DOS operating systems. BASIC Librarian is a full screen program editor, which also provides the ability
[root@localhost sed]# sed 's/^$/.LP/' horse.txt
.LP
Horsefeathers BASIC is BASIC optimized for use on the BigOne machine with UNIX or MS-DOS operating systems. BASIC Librarian is a full screen program editor, which also provides the ability
's/^$/.LP/' 注意:用'.LP'來取代每個空行。在替換指令的替換部分不必轉義字母句點。
b.我們的第二個編輯操作是删除以"+"開始并且包含行式列印機下劃線的行。此處可以用删除指令d隻删除這一行。在編寫比對這一行的模式中,我們可以有許多中不同的選擇,如下的多種形式都可以比對這一行。
/^+/
/^+[空格]/
/^+[空格][空格]*/
/^+[空格][空格]*—*/
可以看出,每個正規表達式一次比對的字元越來越多。隻有通過測試才能決定需要多複雜的表達式來比對特定的行而不是其他的行。在正規表達式中定義的模式越長,就越容易使他不會産生不想要的比對。so,我們選擇了第三種表達式:
[root@localhost sed]# sed '/^+ */d' horse.txt
/^+[空格][空格]*/
注意:這個指令删除以加号開始并且後面跟有至少一個空格的任意行。模式中指定兩個空格。但是第二個可能每個 由“*”号修飾,意味着第二個空格可以有也可以沒有。
c.删除在行開始位置填充的空格。比對序列的模式如下:
s/^[空格][空格]*//
注意:這個指令删除在行的開頭發現的任意空格序列。替換指令的替換部分為空,這意味着删除了被比對的字元串。
eg:
[root@localhost sed]# sed 's/^ *//' horse.txt
requirements for powerful ,sophisticated,general-purpose business software providing you with a base for software customization or development.Horsefeathers BASIC is BASIC optimized for use
on the BigOne machine with UNIX or MS-DOS operating systems. BASIC Librarian is a full screen program editor, which also provides the ability
d.處理為了對齊而添加的額外空格。我們可以編寫一個替換指令比對任意連續空格字元串并用一個空格取代他。
s/ [空格][空格] */[空格]/g
注意:在指令的結尾添加全局标志以便取代所有的出現(不隻是第一個),注意,和前面的正規表達式一樣,我們不能指定有多少空格,可能有一個或者多個,不管有多少,都将他們縮減為一個空格。
友情提示:這個指令還比對單個空格。但是因為替換的指令也是一個空格,是以有一種情況是實際上“沒有工作”。
指令測試:
[root@localhost sed]# sed -e 's/ */ /g' horse.txt
BigOne Computer offers three software packages from the suite of Horsefeather software products -- Horsefeathers Business BASIC Librarian, and LIDO. These software products can fill your
on the BigOne machine with UNIX or MS-DOS operating systems. BASIC Librarian is a full screen program editor, which also provides the ability
上述的表達式有弊端。因為該表達式删除了跟在句點後的兩個空格序列,而在這裡本應該有兩個空格。
so,為了完善替換指令以便他不會替換掉句點後面的空格,問題時句點後面也可能跟有3個空格,則需要将他們删除為2個空格。是以,表達式如下:
s/\.[空格][空格]*/.[空格][空格]/g 此指令可以簡化為: s/\.[空格]/[空格][空格]/g
注意:這個指令用後面跟有兩個空格的句點,替換了後面跟有任意空格的句點。
總結:
s/^$/.LP/
/^+[空格][空格]*/d
s/^[空格]*//
s/[空格][空格]*/[空格]/g
s/\.[空格][空格]*/.[空格][空格]/g
提取宏定義
troff宏在宏包中進行定義,它通常是存放在某個目錄(例如:/usr/lib/macros)下的一個檔案中。troff宏定義總是以字元串'.de'開始,後面跟有可選的空格或者是由一個或者兩個字母構成的宏的名字。宏定義在兩個句點(..)開始的行處結束。本節的内容是從一個宏包中提取特殊的宏定義(它可以節省你用編輯器定位并且打開檔案和搜尋想要檢查的行的時間)。
設計此腳本的第一步是:編寫提取指定宏的部分。
eg:[root@localhost sed]# sed -n '/^\.deBL/','/^\.\.$/p' /usr/lib/macros/mmt
解釋:可以用-n選項來調用sed進而阻止他列印整個檔案,使用這個選項,sed隻列印通過列印指令顯示指定要列印的行。sed腳本包含兩個位址:第一個比對宏定義的開始'.deBL',第二個比對它的終端,"..",(它自成一行).注意:這兩個模式中出現的句點用反斜杠轉義。并且這兩個位址指定了列印指令p的行範圍,這就是搜尋腳本與grep(不能比對行的範圍)功能的差別。
在shell腳本中可以使用位置符号來指定指令行上的每個參數:第一個參數是$1,第二個參數是$2.以此類推。
sed -n "/^\.de$1/,/^\.\.$/p" /usr/lib/macros/mmt注意:包覆sed腳本的雙引号是必須的。如果使用單引号,則shell不對“$1”進行解釋。
例子:此腳本可以處理任意個宏包,下面的getmac版本允許使用者将宏包的名字指定為第二個指令行參數。
[root@localhost sed]# cat getmac
#!/bin/bash
#getmac - read macro definition for $1 from package $2
file=/usr/lib/macros/mmt
mac="$1"
case $2 in
-ms) file="/work/macros/current/tmac.s";;
-mm) file="/usr/lib/macros/mmt";;
-man) file="/usr/lib/macros/an";;
esac
sed -n "/^\.de *$mac/,/^\.\.$/p" $file
解釋:這裡的新内容是case語句,它用于測試$2的值并随後給變量file賦一個值。注意:首先給file賦了一個預設的值。是以如果使用者沒有指定宏包,那麼就會搜尋-mm宏包。而且,為了清楚,易懂,$1的值被指派給了mac。
/^\.de *$mac/:“.de”和宏的名字之間指定了一個空格,後面跟有一個星号,這意味着這個空格是可選的。
生成提綱
文檔例子:
[root@localhost sed]# cat outline.txt
A. Shell Programming
B. Stored Commands
B. Passing Arguments to Shell Scripts
B. Conditional Execution
B. Discarding Used Arguments
B. Repetitive Execution
B. Setting Default Values
B. What We've Accomplished
此腳本需要比對以下面的宏開始的行
** 章标題(.Se)
** 節标題(.Ah)
** 子節标題(.Bh)
如果我們需要在那些行上進行替換,用文本标記(例如:A、B)取代宏并添加适當數量的空格(使用制表符)來縮進每個标題。(記住:"."表示一個制表符)。
s/ "//g s/[{}]//g
指定全局标志g來捕獲一行上的所有出現是必要的。然而,關鍵是将這個腳本放在腳本的什麼位置。如果我們将他放在腳本的結尾,那麼它将在輸出行之後删除引号。我們必須将他放在腳本的起始位置并針對多有的行進行修改,不管他們之後是否在腳本中輸出。
編輯工作轉移
sed作為真正的流程編輯器,在管道中進行編輯操作,這些編輯操作永遠不會被寫回到檔案中。
下面的指令時将兩個連續的破折号轉為一個長破折号。
s/--/\\(em/g
我們在替換字元中用兩個反斜杠來表示\(em。因為反斜杠在sed中有特殊的含義。
/---/!s/--/\(em/g /---/!s/--/\(em/g file | troff
解釋:如果找到含有3個連續的連字元的行,不應用此編輯操作。在所有的其他行上,應用替換指令。後一個表達式的意思是:改變了輸入檔案并且将輸出直接傳遞到troff,而不用建立一個中間檔案。
當一個文檔排版時,将連字元換成長破折号不是唯一要做的美化工作。在troff中,可以通過鍵入兩個連續的重音符或者“反引号('')”來表示左引号。鍵入兩個連續的單引号('')來辨別右引号。我們可以使用sed将每個雙引号字元換成一個單個的左引号或者單個的有引号。也就是說,當排版時,産生合适的“雙引号”。
本文轉自 妙曼 51CTO部落格,原文連結:http://blog.51cto.com/yanruohan/1902746,如需轉載請自行聯系原作者