【linux相識相知】sed命令
在之前的博客中我們介紹了文本三劍客中grep,本次博客就另外一名劍客——sed做出詳細的描述,sed真的是一款強大的工具。下面讓我們來一起看一下吧!
概述和工作機制
SED的英文全稱為Stream EDitor,中文稱流編輯器。默認情況下,它會一行一行的讀取文件中的內容,在了解其工作原理之前,首先我們得先知道一下幾個概念:
1.模式空間(pattern buffer):sed從文件中讀取行首先會放到模式空間中進行執行和處理,定義的sed命令都是在這裏執行的,默認情況下會逐行的讀,逐行的處理,除非你做了行定界。
2.保持空間(hold buffer):在處理完模式空間的一些行的時候,我們有可能需要一個臨時的地方去存放模式空間中的內容,這時候就可以將模式空間中的內容放到保持空間了。
初始情況下,模式空間和保持空間都是空的。
1.默認情況下,將從文件中逐行的讀取內容至模式空間;
2.默認情況下,模式空間中的內容在處理完成後將會打印到標準輸出;
3.sed命令在模式空間中的都是按順序執行的,除非指定了行定界,否則將在所有的行上面執行;
4.修改後的行被送至標準輸出的之後,模式空間將被清空。
基本選項
語法格式:
sed [OPTION]... {script-only-if-no-other-script} [input-file]...
-n:不輸出模式空間中的內容至標準輸出
#例子1 [[email protected]~]# sed ‘‘ /etc/fstab # # /etc/fstab # Created by anaconda on Wed Sep 6 11:16:57 2017 # # Accessible filesystems, by reference, are maintained under ‘/dev/disk‘ # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info # /dev/mapper/cl-root / xfs defaults 00 UUID=0ab24855-5180-4d3e-a61d-99ca54711c2c /boot xfs defaults 0 0 /dev/mapper/cl-swap swap swap defaults 0 0 [[email protected] ~]# #例子2 [[email protected] ~]# sed -n ‘‘ /etc/fstab [[email protected] ~]#
默認情況下,sed命令會逐行的讀取文件中每一行內容至模式空間,再執行執行單引號內的命令,如例子1,單引號內沒有任何內容,所以不會對行內容作任何的處理,所以sed會逐行讀取文件的內容,然後逐行的顯示到標準輸出,每打印一行到標準輸出,模式空間就會被清空一次。在例子2中,加了-n的選項,會阻止輸出到標準輸出,所以就不會顯示任何的內容。
-e script:指定多個命令
[[email protected] ~]# cat poetry 1)Never give up, 2)Never lose hope. 3)Always have faith, 4)It allows you to cope. 5)Trying times will pass, 6)As they always do. 7)Just have patience, 8)Your dreams will come true. 9)So put on a smile, 10)You‘ll live through your pain. 11)Know it will pass, 12)And strength you will gain #例子3 [[email protected] ~]# sed -e ‘1d‘ -e ‘10d‘ poetry 2)Never lose hope. 3)Always have faith, 4)It allows you to cope. 5)Trying times will pass, 6)As they always do. 7)Just have patience, 8)Your dreams will come true. 9)So put on a smile, 11)Know it will pass, 12)And strength you will gain
使用-e選項,可以同時對行作出多個模式匹配,d的意思是刪除。這裏的例子3,文件poetry是輸入,sed讀取第一行的內容至模式1空間,然後判斷是否是第一行,判斷成功是第一行,則刪除第一行(從模式空中清除,也不會打印至標準輸出),讀取第二行,先判斷是否是第一行,不是,再判斷是否是第十行,不是,然後打印至標準輸出,所以在標準輸出中只顯示了不包含第一行和第十行的其他行的內容。註意:sed不會修改原文件的內容。
-f /path/to/script:把sed的編輯命令放在文件中,註意每一行一個命令:
#例子4 [[email protected] ~]# cat sed_script.txt #編輯命令存放的文本文件 1d 10d [[email protected] ~]# sed -f sed_script.txt poetry 2)Never lose hope. 3)Always have faith, 4)It allows you to cope. 5)Trying times will pass, 6)As they always do. 7)Just have patience, 8)Your dreams will come true. 9)So put on a smile, 11)Know it will pass, 12)And strength you will gain
我們可以看到例子4中sed使用-f選項指定編輯命令所在的文件,執行的是和例子3同樣的操作,刪除第一行和第十行,當我們得編輯命令有很多,把它放在文件也是一個不錯的做法吧!
行定界
默認情況下不指定行的定界,會讀取處理整個文件的每一行。如果指定了行,還是會讀取每一行,但是在執行各種命令操作之後,會進行判斷是不是定界的行,如果判斷成功,則執行操作,如刪除行,如果判斷失敗,則不做任何的處理然後打印至標準輸出,下面來看一下幾種常見的定界方法:
(1)定界為空,對全文的每一行進行處理
[[email protected] ~]# sed ‘‘ poetry 1)Never give up, 2)Never lose hope. 3)Always have faith, 4)It allows you to cope. 5)Trying times will pass, 6)As they always do. 7)Just have patience, 8)Your dreams will come true. 9)So put on a smile, 10)You‘ll live through your pain. 11)Know it will pass, 12)And strength you will gain(2)單行指定 a.直接寫單個數字,表示指定行
[[email protected] ~]# sed ‘2d‘ poetry #當判斷為第二行的時候,會刪除第二行 1)Never give up, 3)Always have faith, 4)It allows you to cope. 5)Trying times will pass, 6)As they always do. 7)Just have patience, 8)Your dreams will come true. 9)So put on a smile, 10)You‘ll live through your pain. 11)Know it will pass, 12)And strength you will gain
b./pattern/:被模式匹配到的行,默認可以是基本的正在表達式
[[email protected] ~]# sed ‘/As/ d‘ poetry #刪除被模式匹配的行 1)Never give up, 2)Never lose hope. 3)Always have faith, 4)It allows you to cope. 5)Trying times will pass, 7)Just have patience, 8)Your dreams will come true. 9)So put on a smile, 10)You‘ll live through your pain. 11)Know it will pass, 12)And strength you will gain
c.$最後一行
[[email protected] ~]# sed ‘$ d‘ poetry #刪除最後一行 1)Never give up, 2)Never lose hope. 3)Always have faith, 4)It allows you to cope. 5)Trying times will pass, 6)As they always do. 7)Just have patience, 8)Your dreams will come true. 9)So put on a smile, 10)You‘ll live through your pain. 11)Know it will pass,
(3)定界範圍
a.x,y:x至y行
[[email protected] ~]# sed ‘1,9 d‘ poetry #刪除了1-9行 10)You‘ll live through your pain. 11)Know it will pass, 12)And strength you will gain
b.x,+y:x行到,x行往下數y個行
[[email protected] ~]# sed ‘1,+3 d‘ poetry #刪除第一行,和第一行往下的3行,也就是一直刪除到第四行 5)Trying times will pass, 6)As they always do. 7)Just have patience, 8)Your dreams will come true. 9)So put on a smile, 10)You‘ll live through your pain. 11)Know it will pass, 12)And strength you will gain
c.x,/pattren/:x到被模式匹配的行
[[email protected] ~]# sed ‘2,/smile/ d‘ poetry #刪除第二行至被smile匹配的行,smile被第九行匹配 1)Never give up, 10)You‘ll live through your pain. 11)Know it will pass, 12)And strength you will gain
d./pattren1/,/pattern2/:被模式1匹配的行開始到被模式2匹配的行
[[email protected] ~]# sed ‘/Always/,/put/ d‘ poetry 1)Never give up, 2)Never lose hope. 10)You‘ll live through your pain. 11)Know it will pass, 12)And strength you will gain(4)使用"~"指定步進 "~"號前面為開始行,後面為步進的長度:
[[email protected] ~]# sed ‘1~2 d‘ poetry #顯示偶數行 2)Never lose hope. 4)It allows you to cope. 6)As they always do. 8)Your dreams will come true. 10)You‘ll live through your pain. 12)And strength you will gain [[email protected] ~]# sed ‘2~2 d‘ poetry #顯示奇數行 1)Never give up, 3)Always have faith, 5)Trying times will pass, 7)Just have patience, 9)So put on a smile, 11)Know it will pass,
編輯命令
下面我們來看一下編輯命令,如前面的d選項是刪除行的意思,那麽除了d選項,還有哪些呢?
p:顯示模式空間的內容
#例5 [[email protected] ~]# sed ‘p‘ poetry 1)Never give up, 1)Never give up, 2)Never lose hope. 2)Never lose hope. 3)Always have faith, 3)Always have faith, 4)It allows you to cope. 4)It allows you to cope. 5)Trying times will pass, 5)Trying times will pass, 6)As they always do. 6)As they always do. 7)Just have patience, 7)Just have patience, 8)Your dreams will come true. 8)Your dreams will come true. 9)So put on a smile, 9)So put on a smile, 10)You‘ll live through your pain. 10)You‘ll live through your pain. 11)Know it will pass, 11)Know it will pass, 12)And strength you will gain 12)And strength you will gain #例6 [[email protected] ~]# sed -n ‘p‘ poetry 1)Never give up, 2)Never lose hope. 3)Always have faith, 4)It allows you to cope. 5)Trying times will pass, 6)As they always do. 7)Just have patience, 8)Your dreams will come true. 9)So put on a smile, 10)You‘ll live through your pain. 11)Know it will pass, 12)And strength you will gainView Code
在例5中,每一行都被打印了2次,原因是在模式空間的時候被打印了一次,然後處理完成之後,在標準輸出又被打印了一次,所以自然會顯示出兩次。如果使用-n,則僅僅打印的模式空間的內容。
a test:在行後面追加文本"test",可以使用\n實現多行追加
[[email protected] ~]# sed ‘1 a hi i am here\nhey ‘ poetry 1)Never give up, hi i am here hey 2)Never lose hope. 3)Always have faith, 4)It allows you to cope. 5)Trying times will pass, 6)As they always do. 7)Just have patience, 8)Your dreams will come true. 9)So put on a smile, 10)You‘ll live through your pain. 11)Know it will pass, 12)And strength you will gain
i test:在 行前面插入文本test,支持使用\n實現多行插入
[[email protected] ~]# sed ‘2i hi i am here\nhey ‘ poetry 1)Never give up, hi i am here hey 2)Never lose hope. 3)Always have faith, 4)It allows you to cope. 5)Trying times will pass, 6)As they always do. 7)Just have patience, 8)Your dreams will come true. 9)So put on a smile, 10)You‘ll live through your pain. 11)Know it will pass, 12)And strength you will gain
c test:把匹配到的行替換為此處指定的行
[[email protected] ~]# sed ‘2c hi i am here ‘ poetry 1)Never give up, hi i am here 3)Always have faith, 4)It allows you to cope. 5)Trying times will pass, 6)As they always do. 7)Just have patience, 8)Your dreams will come true. 9)So put on a smile, 10)You‘ll live through your pain. 11)Know it will pass, 12)And strength you will gain
w /path/to/somefile:保存模式空間中匹配到的內容到指定的文件中
[[email protected] ~]# sed ‘/So/ w /tmp/poetry‘ poetry 1)Never give up, 2)Never lose hope. 3)Always have faith, 4)It allows you to cope. 5)Trying times will pass, 6)As they always do. 7)Just have patience, 8)Your dreams will come true. 9)So put on a smile, 10)You‘ll live through your pain. 11)Know it will pass, 12)And strength you will gain [[email protected] ~]# [[email protected] ~]# cat /tmp/poetry 9)So put on a smile,
r /path/from/somefile:讀取指定文件的內容至當前文件中被模式匹配的行後面
[[email protected] ~]# cat poetry2.txt 13)yes! I can! [[email protected] ~]# sed ‘12 r poetry2.txt‘ poetry 1)Never give up, 2)Never lose hope. 3)Always have faith, 4)It allows you to cope. 5)Trying times will pass, 6)As they always do. 7)Just have patience, 8)Your dreams will come true. 9)So put on a smile, 10)You‘ll live through your pain. 11)Know it will pass, 12)And strength you will gain 13)yes! I can!
=:為模式匹配到的行打印行號,打印在行的上面
[[email protected] ~]# sed ‘/Never/ =‘ poetry 1 1)Never give up, 2 2)Never lose hope. 3)Always have faith, 4)It allows you to cope. 5)Trying times will pass, 6)As they always do. 7)Just have patience, 8)Your dreams will come true. 9)So put on a smile, 10)You‘ll live through your pain. 11)Know it will pass, 12)And strength you will gain
!:條件取反
[[email protected] ~]# sed ‘/Never/ !d‘ poetry #不刪除被默認匹配的行 1)Never give up, 2)Never lose hope.
s///:查找替換,分割符可以自定義,比如使用[email protected]@@flag或者s###flag,默認會替換被匹配的第一個位置,但是可以添加替換標記:
s///g:全局替換
[[email protected] ~]# cat poetry 1)Never give up, 2)Never lose hope. 3)Always have faith, 4)It allows you to cope. 5)Trying times will pass, 6)As they always do. 7)Just have patience, 8)Your dreams will come true. 9)So put on a smile, 10)You‘ll live through your pain. 11)Know it will pass, 12)And strength you will gain [[email protected] ~]# sed ‘s/\<you\>/your/g‘ poetry 1)Never give up, 2)Never lose hope. 3)Always have faith, 4)It allows your to cope. 5)Trying times will pass, 6)As they always do. 7)Just have patience, 8)Your dreams will come true. 9)So put on a smile, 10)You‘ll live through your pain. 11)Know it will pass, 12)And strength your will gainView Code
sed默認支持的基本的正則表達式,使用-r, --regexp-extended選項可以支持擴展的正則表達式。
練習1:刪除/boot/grub2/grub.cfg文件中所有以空白字符開頭的行的行首的所有空白字符
[[email protected] ~]# sed -r ‘[email protected]^[[:space:]][email protected]@g‘ /boot/grub2/grub.cfgView Code
練習2:刪除/etc/fstab文件中所有以#開頭的行的行首的#號及#後面的所有空白字符
[[email protected] ~]# sed ‘s/^#[[:space:]]*//g‘ /etc/fstabView Code
練習3:輸出一個目錄給sed,取出其目錄,類似於dirname
[[email protected] ~]# echo "/var/log/messages" | sed -r ‘[email protected][^/]+/[email protected]@‘ /var/log/ [[email protected] ~]# [[email protected] ~]# echo "/var/log/messages/" | sed -r ‘[email protected][^/]+/[email protected]@‘ /var/log/View Code
高級編輯命令
sed還有一些高級的命令,會用到之前說到的保持空間。
舉一些例子來看一下吧!
[[email protected] ~]# cat poetry 1)Never give up, 2)Never lose hope. 3)Always have faith, 4)It allows you to cope. 5)Trying times will pass, 6)As they always do. 7)Just have patience, 8)Your dreams will come true. 9)So put on a smile, 10)You‘ll live through your pain. 11)Know it will pass, 12)And strength you will gain
可以自己先思考一下答案,再點開:
[[email protected] ~]# sed -n ‘n;p‘ poetry #只顯示偶數行 2)Never lose hope. 4)It allows you to cope. 6)As they always do. 8)Your dreams will come true. 10)You‘ll live through your pain. 12)And strength you will gainsed -n ‘n;p‘ poetry
[[email protected] ~]# sed ‘1!G;h;$!d‘ poetry #逆序顯示 12)And strength you will gain 11)Know it will pass, 10)You‘ll live through your pain. 9)So put on a smile, 8)Your dreams will come true. 7)Just have patience, 6)As they always do. 5)Trying times will pass, 4)It allows you to cope. 3)Always have faith, 2)Never lose hope. 1)Never give up,sed ‘1!G;h;$!d‘ poetry
[[email protected] ~]# sed ‘$!d‘ poetry #只保留最後一行,類似tail -1 12)And strength you will gainsed ‘$!d‘ poetry
[[email protected] ~]# sed ‘$!N;$!D‘ poetry #取出最後兩行 11)Know it will pass, 12)And strength you will gainsed ‘$!N;$!D‘ poetry
[[email protected] ~]# sed ‘G‘ poetry #在每一行的後面添加一個空白行 1)Never give up, 2)Never lose hope. 3)Always have faith, 4)It allows you to cope. 5)Trying times will pass, 6)As they always do. 7)Just have patience, 8)Your dreams will come true. 9)So put on a smile, 10)You‘ll live through your pain. 11)Know it will pass, 12)And strength you will gainsed ‘G‘ poetry
這些都是一些高級的用法,在工作中用的可能比較少,因為有的結果完全可以用其他簡單的命令去實現。
循環和分支
sed最牛逼之處莫過於這個了,sed提供了一個循環和分支工來控制程序的執行流程。
循環
sed循環的工作原理類似於現代編程語言中的goto語句。
定義sed的標簽:
:label
跳轉到標簽的位置,使用b命令後面跟著標簽名即可,下面我們來看一個具體的實例:
[[email protected] ~]# cat teleplay 劇名:白夜追兇 評分:9.0 劇名:秘密深林 評分:9.3 劇名:權利的遊戲第七季 評分:9.3 劇名:請回答1988 評分:9.6 [[email protected] ~]# sed -n ‘ h;n;H;x [email protected]\[email protected],@ /請回答/!b label [email protected]^@---@ :label p‘ teleplay 劇名:白夜追兇,評分:9.0 劇名:秘密深林,評分:9.3 劇名:權利的遊戲第七季,評分:9.3 ---劇名:請回答1988,評分:9.6
分析:
由於命令很長,我們可以將命令分行來寫,當然也可以寫在一行裏面:
1.h;n;H;x:將第一行內容讀取到模式空間,執行h,將模式空間的內容覆蓋至保持空間,執行n,從文件中讀取第二行覆蓋至模式空間,執行H,將模式空間的內容追加至保持空間,執行x,將保持空間的內容和模式空間調換;(這裏得到的結果就是模式空間中存在兩行);
[email protected]\[email protected],@,將換行符替換為逗號;這樣原來的兩行就變成了一行;
3./請回答/!b label,判斷這一行中是否有“請回答”三個字符,如果沒有則直接跳到":label",然後執行打印"p",打印模式空間中的內容,如果有則執行"[email protected]^@[email protected]",將在行首添加字符"---"。
這樣一來,只有"劇名:請回答1988,評分:9.6"被匹配,然後進行了行首的替換操作。
分支
可以使用t來創建分支。使用t命令跳轉到指定的標簽,一樣我們來看一個例子:
[[email protected] ~]# sed -n ‘ > h;n;H;x > s/\n/,/ > :loop > /白夜追兇/s/^/-/ > /-----/!t loop > p‘ teleplay -----劇名:白夜追兇,評分:9.0 劇名:秘密深林,評分:9.3 劇名:權利的遊戲第七季,評分:9.3 劇名:請回答1988,評分:9.6
分析:
由於命令很長,我們可以將命令分行來寫,當然也可以寫在一行裏面:
1:h;n;H;x:將第一行內容讀取到模式空間,執行h,將模式空間的內容覆蓋至保持空間,執行n,從文件中讀取第二行覆蓋至模式空間,執行H,將模式空間的內容追加至保持空間,執行x,將保持空間的內容和模式空間調換;(這裏得到的結果就是模式空間中存在兩行);
2:[email protected]\[email protected],@,將換行符替換為逗號;這樣原來的兩行就變成了一行;
3::loop:定義了一個loop標簽;
4:/白夜追兇/s/^/-/:是否匹配模式,如果匹配則在其行首添加一個"-";如果不匹配,則直接打印;
5:/-----/!t loop:是否存在5個"-",如果不存在,則跳到標簽loop處,繼續執行第4步添加"-",直到滿足5個"-",則跳出循環打印。
最後,我們之前的所有的操作,都是沒有修改文件的本身的,可以使用 -i 選項來直接修改文件本身,慎用,建議在使用之前,先備份一下文件!
[[email protected] ~]# sed -i ‘1d‘ poetry [[email protected] ~]# [[email protected] ~]# cat poetry 2)Never lose hope. 3)Always have faith, 4)It allows you to cope. 5)Trying times will pass, 6)As they always do. 7)Just have patience, 8)Your dreams will come true. 9)So put on a smile, 10)You‘ll live through your pain. 11)Know it will pass, 12)And strength you will gain
總結:sed的確是一個強大的文本處理工具,功能非常豐富,需要在今後的日常使用和工作中不斷的熟悉和鞏固。
參考鏈接:http://blog.jobbole.com/109088/ 《三分鐘學會SED》寫的非常好!
【linux相識相知】sed命令