SED(Stream EDitor)流編輯器囤采,是Unix下一款文本處理工具宇色。SED 是 Lee E. McMahon 從1973到1974 在貝爾實驗室開發(fā)的。SED有多種用途善绎,主要用于:
- 文本替換灵寺;
- 選擇性打印文本;
- 就地編輯文件慈省;
- 非交互式編輯文件臀防;
- 其它...;
1.執(zhí)行流程
SED循環(huán)簡單執(zhí)行流程:讀取->執(zhí)行->展示边败,如下圖:
讀雀ぶ浴:
sed從輸入流(文件、標(biāo)準(zhǔn)輸入笑窜、管道)中讀取一行致燥,并將內(nèi)容存儲在pattern buffer中,pattern buffer后邊會講到怖侦。
執(zhí)行:
sed命令會串行地應(yīng)用于pattern buffer中的內(nèi)容篡悟,默認(rèn)情況下,這sed命令會應(yīng)用于第一行匾寝,除非指定行地址搬葬。后面會說到具體細(xì)節(jié)。
展示:
將修改后的內(nèi)容發(fā)送到輸出流中(標(biāo)準(zhǔn)輸出艳悔、管道急凰、文件),輸出完后猜年,清空緩沖區(qū)抡锈。
以上步驟會循環(huán)執(zhí)行,直到達(dá)到文件末尾乔外。簡單地說sed就是從輸入流中逐行進(jìn)行以上三個步驟床三,理解sed的執(zhí)行流程對下面的學(xué)習(xí)至關(guān)重要。
2. 學(xué)習(xí)sed的關(guān)鍵點
- pattern buffer是sed用于存儲輸入行的內(nèi)存區(qū)域杨幼,sed命令只能作用于pattern buffer撇簿,一旦sed命令作用于pattern buffer的結(jié)果發(fā)送至輸出流后,pattern buffer自動被清空差购;
- hold buffer也是sed的一塊內(nèi)存區(qū)域四瘫,但sed命令不能直接作用于hold buffer。所以sed提供了一些命令用于pattern buffer和hold buffer之后進(jìn)行數(shù)據(jù)交換欲逃,后邊會詳細(xì)講到找蜜;
- sed初始化時,pattern buffer和hold buffer均為空稳析;
- 默認(rèn)情況下洗做,如果未指定行地址,sed將作用于每一行迈着;
- 如果沒有指定輸入文件竭望,sed將標(biāo)準(zhǔn)輸入作為輸入文件;
3. 基本語法
sed [-n] [-e] 'command(s)' files
sed [-n] -f scriptfile files
先看一個sed實例:
shell> cat books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
shell> sed '' book.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
sed命令可以為空裕菠,默認(rèn)情況下咬清,sed會將讀取的每一行輸出至標(biāo)準(zhǔn)輸出。如果我們指定-n
參數(shù)奴潘,表示關(guān)閉默認(rèn)輸出:
shell> sed -n '' books.txt
你會發(fā)現(xiàn)上面命令執(zhí)行后沒有任何輸出旧烧。關(guān)閉默認(rèn)輸出后,我們可以通過sed的p
命令輸出画髓,并且可以指定輸出行掘剪,如3p
表示只輸出第三行,如:
shell> sed -n '3p' books.txt
3) The Alchemist, Paulo Coelho, 197
我們可以將命令放到文件中奈虾,通過-f
參數(shù)指定sed命令文件夺谁,如:
shell> echo '3p' > commands.txt
shell> sed -n -f commands.txt books.txt
3) The Alchemist, Paulo Coelho, 197
可以使用-e
參數(shù)拼接多個sed命令廉赔,如:
shell> sed -n -e '1p' -e '3p' -e '5p' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
3) The Alchemist, Paulo Coelho, 197
5) The Pilgrimage, Paulo Coelho, 288
使用-i
參數(shù)表示就地修改文件,這個地方我們先說一下sed的d
命令匾鸥,表示刪除(delete)蜡塌,同樣可以在前面指定行號,如3d
表示刪除第三行如:
shell> sed '3d' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
執(zhí)行完上述命令后勿负,我們打開books.txt馏艾,發(fā)現(xiàn)文件并沒有刪除第三行,默認(rèn)情況下奴愉,sed命令只是將結(jié)果輸出至標(biāo)準(zhǔn)輸出琅摩,如果指定了-i
,就會直接修改源文件:
shell> sed -i '3d' books.txt
shell> cat books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
更多sed參數(shù)請自行man sed
锭硼。
4. 模式范圍
在學(xué)習(xí)sed命令之前房资,需要先學(xué)習(xí)一下模式范圍,因為模式范圍基本上對所有sed命令是通用的檀头。
前面學(xué)習(xí)了命令p
表示打印至標(biāo)準(zhǔn)輸出志膀,并且可以指定行號。如前面說的3p
表示打印第3行鳖擒,打印最后一行溉浙,用$
表示,
shell> sed -n '$p' books.txt
6) A Game of Thrones, George R. R. Martin, 864
除了指定具體行號外蒋荚,還可以指定行號范圍戳稽,中間用分號
分隔,如打印2到4行:
shell> sed -n '2,4p' books.txt
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
使用M,+n
表示sed會處理M行開始的n行期升,如2,+2p
表示打印從第2行開始的后面2行:
shell> sed -n '2,+2p' books.txt
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
使用M~n
表示sed會處理從M行開始的第隔n行惊奇,如果1~2p
表示打印奇數(shù)行:
shell> sed -n '1~2p' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
3) The Alchemist, Paulo Coelho, 197
5) The Pilgrimage, Paulo Coelho, 288
除了指定行號范圍外,還可以通過模式匹配行號進(jìn)行處理播赁,同樣以sed命令p
為例颂郎,打印出現(xiàn)Paulo
的行:
shell> sed -n '/Paulo/ p' books.txt
3) The Alchemist, Paulo Coelho, 197
5) The Pilgrimage, Paulo Coelho, 288
也可以將模式匹配跟行號結(jié)合使用指定一個范圍,如/Paulo/, 4p
表示打印匹配到Paulo
的行和到第4行:
shell> sed -n '/Paulo/, 4p' books.txt
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
也可以使用將模式匹配跟+n
組合容为,表示打印匹配行之后的n行:
shell> sed -n '/Fellowship/, +2p' books.txt
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
也可以指定模式匹配范圍乓序,仍然使用分號
分隔,如/Two/, /Fellowship/ p
表示打印匹配到Two
和匹配到Fellowship
中間的行:
shell> sed -n '/Two/, /Fellowship/ p' books.txt
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5. 正則匹配
由于在sed命令中坎背,正則表達(dá)式使用的比較多替劈,但正則表達(dá)式有學(xué)習(xí)成本,可以先學(xué)習(xí)一下常用的正則表達(dá)式得滤,更多正則表達(dá)式的知識可以參考Regular expression陨献。
正則表達(dá)式 | 說明 |
---|---|
^ | 匹配行的開始 |
$ | 匹配行的結(jié)尾 |
. | 匹配單個字符 |
[] | 匹配字符集,如[abc] 匹配字符a 或b 或c
|
[^] | 非匹配字符集懂更,如[0-9] 匹配非數(shù)字字符 |
[-] | 匹配字符范圍眨业,如[a-z] 匹配a 到z 的字符 |
? | 匹配0個或1個字符 |
+ | 匹配1個或多個字符 |
* | 匹配0個或多個字符 |
{n} | 匹配出現(xiàn)n次 |
{n,} | 匹配至少出現(xiàn)n次 |
{n,m} | 匹配出現(xiàn)n到m次 |
| | 選擇急膀,如str(1|2|3) 匹配str1,str2,str3
|
() | 分組 |
有了正則表達(dá)式基礎(chǔ),再來看下sed的
sed基本命令替換命令s
龄捡,其語法如下:
[address1[,address2]]s/pattern/replacement/[flags]
如果我們想替換books.txt
文件中第一行中的Martin
為Brown
:
shell> sed -n '1 s/Martin/Brown/p' books.txt
1) A Storm of Swords, George R. R. Brown, 1216
使用i
標(biāo)記可以忽略大小寫進(jìn)行匹配:
shell> sed -n 's/pAuLo CoElHo/PAULO COELHO/pi' books.txt
3) The Alchemist, PAULO COELHO, 197
5) The Pilgrimage, PAULO COELHO, 288
再來看下分組匹配:
shell>echo "Three One Two" | sed 's/\(\w\+\) \(\w\+\) \(\w\+\)/\2 \3 \1/'
One Two Three
上面命令通過\w\+
匹配單詞進(jìn)行分組脖阵,通過\1 \2 \3
索引分組,索引順序按照分組順序墅茉,然后再分組重排列進(jìn)行輸出。
6. 基本命令
6.1 d命令
d命令前面提到了呜呐,為刪除命令就斤,前面可以指定地址范圍,地址范圍格式參考模式范圍蘑辑,d命令語法如下:
[address1[,address2]]d
刪除books.txt
文件中的2到4行洋机,如下:
shell> sed '2,4d' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
6.2 w命令
w為寫(write)命令,表示將匹配的地址寫入到指定文件中洋魂,地址格式參考模式范圍绷旗,w命令語法如下:
[address1[,address2]]w file
將books.txt
的2到4行寫入到文件tmp.txt
中
shell> sed -n '2,4w tmp.txt' books.txt
shell> cat tmp.txt
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
6.3 r命令
r為讀(read)命令,表示將從指定文件中讀取內(nèi)容到指定地址中副砍,地址格式參考模式范圍衔肢,r命令語法如下:
[address]r file
將文件junk.txt
的內(nèi)容寫入到books.txt
的第3行后面,如下:
shell> cat junk.txt
This is junk text.
shell> sed '3 r junk.txt' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
This is junk text.
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
6.4 a命令
a為追回(append)命令豁翎,表示將指定的內(nèi)容追回到指定地址中角骤,地址格式參考模式范圍,a命令語法如下:
[address]a Append text
在books.txt
文件的第4行追回內(nèi)容7) Adultry, Paulo Coelho, 234' books.txt
心剥,如下:
shell> sed '4 a 7) Adultry, Paulo Coelho, 234' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
7) Adultry, Paulo Coelho, 234
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
6.5 i命令
i為插入(insert)命令邦尊,表示將指定內(nèi)容播放到指定地址中,地址格式參考模式范圍优烧,i命令語法如下:
[address]i Insert text
在books.txt
文件的第4行插入內(nèi)容7) Adultry, Paulo Coelho, 234' books.txt
蝉揍,如下:
shell> sed '4 i 7) Adultry, Paulo Coelho, 234' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
7) Adultry, Paulo Coelho, 234
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
6.6 c命令
c為修改(change)命令,表示在指定地址中替換指定內(nèi)容畦娄,地址格式參考模式范圍又沾,c命令語法如下:
[address1[,address2]]c Replace text
將文件books.txt
的第3行替換為3) Adultry, Paulo Coelho, 324
,如下:
shell> sed '3 c 3) Adultry, Paulo Coelho, 324' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) Adultry, Paulo Coelho, 324
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
6.7 y命令
y為轉(zhuǎn)換命令熙卡,有點類似于tr
命令捍掺,即將一組字符轉(zhuǎn)換成另一組字符,語法格式如下:
[address1[,address2]]y/list-1/list-2/
將數(shù)字0123456789
映射為xabcdefghi
再膳,如下:
shell> echo '1122345690' | sed 'y/0123456789/xabcdefghi'
aabbcdefix
6.8 n命令
n為讀取下一行(next)命令挺勿,n命令經(jīng)常用于連接其它命令,看下面示例:
sed command1
sed command2
n
sed command3
sed command4
sed在讀取一行后喂柒,將讀取行存入到pattern buffer中不瓶,然后分別將sed command1
和sed command2
作用于pattern buffer中的內(nèi)容禾嫉,到執(zhí)行n的時候,sed會讀取下一行到pattern buffer中蚊丐,然后分別將sed command3
和sed command4
作用于pattern buffer中的內(nèi)容(下一行的內(nèi)容)熙参。請務(wù)必理解n命令的工作方式,下面例子是打印books.txt
文件中偶數(shù)行的內(nèi)容:
shell> sed -n 'n;p' books.txt
2) The Two Towers, J. R. R. Tolkien, 352
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
6) A Game of Thrones, George R. R. Martin, 864
sed首先讀取第一行麦备,然后執(zhí)行n
命令時孽椰,按照n命令的工作方式,n讀取下一行(也就是第二行)凛篙,將其內(nèi)容放到pattern buffer中黍匾,然后執(zhí)行p命令,將pattern buffer中的內(nèi)容輸出呛梆。依次執(zhí)行文件后續(xù)行锐涯,直到文件到達(dá)結(jié)尾。
6.9 N命令
和n
命令不同的是填物,N命令是將讀取的下一行的內(nèi)容添加換行符(\n
)后追加到pattern buffer中纹腌,如:
shell> sed -n 'N;s/\n/;/g;p' books.txt
1) A Storm of Swords, George R. R. Martin, 1216 ; 2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197; 4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288 ; 6) A Game of Thrones, George R. R. Martin, 864
以上命令的工作方式是:
首先sed讀取第一行,存和pattern buffer中滞磺,然后執(zhí)行N命令升薯,按照N命令的工作方式,先是添加一個換行符击困,然后再將下一行(第二行)的內(nèi)容一并追加至pattern buffer中覆劈,然后我們執(zhí)行s/\n/;/g
將換行符替換為;
,最后輸出沛励。
6.10 P命令
P命令也是打印责语,和p
命令不同的,P命令只是打印N命令換行符前面的內(nèi)容目派,如:
shell> sed -n 'N;P' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
3) The Alchemist, Paulo Coelho, 197
5) The Pilgrimage, Paulo Coelho, 288
如果沒有N命令坤候,P命令等同于p命令。
6.11 e命令
e為執(zhí)行(execute)命令企蹭,sed可以執(zhí)行外部命令白筹,并將執(zhí)行結(jié)果插入到指定地址前面,其語法如下:
[address1[,address2]]e [command]
如將命令date
的結(jié)果插入文件books.txt
的第3行谅摄,如下:
shell> sed '3 e date' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
Sat Jun 22 23:42:12 CST 2019
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
6.12 q命令
q為退出(quit)命令徒河,表示退出本次執(zhí)行流程,其語法如下:
[address]q [value]
其中value中退出返回碼送漠,如:
shell> sed '2 q 100' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
shell> echo $?
100
模式管理
最后我們講一下模式管理顽照,也是sed的一些高級用法。前面提到了hold buffer
,但我們從來沒有用過代兵,前面我們已經(jīng)知道尼酿,sed命令只能作用于pattern buffer
,
不能作用于hold buffer
植影,所以sed提供了以下命令裳擎,供pattern buffer和hold buffer之間進(jìn)行數(shù)據(jù)交換,如下:
命令 | 說明 |
---|---|
h | 將pattern buffer中的內(nèi)容拷貝至hold buffer中思币,hold buffer中的內(nèi)容會被覆蓋 |
H | 將pattern buffer中的內(nèi)容追回到hold buffer中 |
g | 將hold buffer中的內(nèi)容拷貝至pattern buffer中鹿响,pattern buffer中的內(nèi)容會被覆蓋 |
G | 將hold buffer中的內(nèi)容追回至pattern buffer中 |
x | 交換pattern buffer和hold buffer之間內(nèi)容 |
如何使用呢,下面例子是將文件books.txt中的內(nèi)容逆置:
shell> sed -n '1!G;h;$!d;p' books.txt
6) A Game of Thrones, George R. R. Martin, 864
5) The Pilgrimage, Paulo Coelho, 288
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
3) The Alchemist, Paulo Coelho, 197
2) The Two Towers, J. R. R. Tolkien, 352
1) A Storm of Swords, George R. R. Martin, 1216
來看一下執(zhí)行步驟:
- sed首先讀取一行谷饿,對一行來講惶我,就是
1) A Storm of Swords, George R. R. Martin, 1216
,并將其存儲在pattern buffer中各墨, -
1!G
:該命令表示除第一行外,將hold buffer中的內(nèi)容追回到pattern buffer中启涯。 -
h
:該命令會將pattern buffer中的內(nèi)容copy至hold buffer中贬堵; -
$1d
:該命令表示除了最后一行,將刪除pattern buffer中的內(nèi)容结洼;
通過以上步驟的解析我們可以知道黎做,其工作原理有點像單鏈表逆置。即除第一行外松忍,將hold buffer中的內(nèi)容追回到pattern buffer中蒸殿,然后再將pattern buffer中的內(nèi)容存儲到hold buffer中,循環(huán)執(zhí)行直到最后一次鸣峭。對于第一輪循環(huán)宏所,如果不是最后一行,則刪除pattern buffer中的內(nèi)容摊溶;對于輸出操作爬骤,由于除最后一次外,pattern buffer中的內(nèi)容都被清空莫换,所以最終輸出為執(zhí)行最后一行的時候pattern buffer中的內(nèi)容霞玄。
7. 參考
[1] https://en.wikipedia.org/wiki/Sed
[2] https://www.tutorialspoint.com/sed/index.htm
[3] https://coolshell.cn/articles/9104.html