以前介紹了三大文本編輯器的grep,這裏介紹比grep功能更強的sed流編輯器正則表達式
sed是什麼?express
sed是Stream EDitor的縮寫,man中對sed的簡介爲centos
sed - stream editor for filtering and transforming text緩存
它的主要功能是對文本的過濾與替換。bash
sed的工做原理
app
sed的工做過程:sed是一個流編輯器,所謂流編輯器是指sed每次只從文件或stdin中讀入一行,將讀入的行保存至模式空間而後根據指定的要求對其進行處理,並將處理後的結果輸出至屏幕,接着讀入下一行,整個文本的過程如流水線般被逐行處理後輸出。編輯器
sed對內容的處理方式:sed不是在原文件中或原輸入上直接進行處理的,它將讀入的行放入緩存區,對緩存區裏的內容進行處理,處理完畢後默認不會寫入或覆蓋源文件,而是直接輸出到屏幕上。ide
它有兩個內存緩衝區分別叫作:模式空間(pattern space)、保持空間也有稱做暫存緩存區(holding space)。工具
通常狀況下sed首先把第一行裝入模式空間,進行處理後輸出屏幕,而後第二行裝入模式空間替換掉模式空間裏原來的內容,再進行處理,依次循環,直至結束。學習
下面是我對sed工做流程的理解圖。
一、sed每次將stdin中的內容中的一行讀入模式空間
二、以後根據模式空間中的匹配條件進行匹配,符合條件進入下一階段即普通編輯,不知足則默認至標準輸出,結束
三、普通編輯以後分三個階段,1)普通編輯以後選擇性顯示至STDOUT,結束;2)進入holding space進行高級編輯,編輯結束後選擇性顯示至模式空間,以後再次根據編輯命令重複2-3過程;3)如果出現多編輯命令則須要再返回模式空間根據編輯條件再次進行2-3步驟。
限於我的理解程度上述的理解免不了跟真實的工做流程有些出入,你們要抱着質疑的態度去看,我寫的不必定都是對的,不過錯的應該不至於不少。
sed語法
sed OPTIONS... <SCRIPT> [INPUTFILE...]
[SCRIPT]:能夠理解爲地址定界加編輯命令。
經常使用選項:
-n:不輸出模式空間中的內容至屏幕;通俗點能夠理解爲它能夠自動過濾掉模式空間中未匹配到的行,-n 要與命令編輯中的p合用(命令編輯見下文),用於顯示模式空間中被匹配到的內容。
suppress automatic printing of pattern space
-n的具體應用見後面的sed編輯高級命令演示
-e:多點編輯
add the script to the commands to be executed
-f:每行一個編輯命令
add the contents of script-file to the commands to be executed
-r:使用擴展表達式
use extended regular expressions in the script.
-i:直接編輯原文件
edit files in place (makes backup if SUFFIX supplied)
SCRIPT:
以前對這塊很迷糊,由於info中sed顯示語法有[]表示可加可不加,因而就在sed後直接加想要編輯的文本
因而就出現以下狀況
[root@localhost test]# sed sed1 sed:-e 表達式 #1,字符 4:未終止的「s」命令
報錯信息沒找到終止的限制條件,因此上面的sed語法格式並不許確。
經過實驗,sed能夠不加[OPTION]可是[SCRIPT]則必須添加
SCRIPT分兩部分:地址定界(用於限定編輯文本的範圍)、編輯命令(用於對匹配到的內容進行什麼樣的操做或編輯),前者可少後者必不可少,若是沒有編輯的命令會發生以下錯誤
[root@localhost test]# sed '1' cat1 sed:-e 表達式 #1,字符 1:遺漏命令 [root@localhost test]# cat cat1 hi,everyone now I will show how to use cat [root@localhost test]# sed 'p' cat1 hi,everyone hi,everyone now I will show how to use cat now I will show how to use cat
地址定界:
一、空地址:對全文處理。
二、單地址:
#:指定行;
/pattern/:被此模式所匹配到的每一行;
三、地址範圍:
#,#:從#開始到#結束的全部行
#,+#:從#開始向下至+#的行之間的全部行
#,/pat1/ 從#開始至匹配到第一次出現/pat1/模式的行之間的全部行
/pat1/,/pat2/:第一次匹配到/pat1/的行到第一次匹配到/pat2/的行之間的全部行
四、步進:~
1~2:全部奇數行 2~2:全部偶數行
編輯命令:若少了編輯命令會報錯,編輯命令在SCRIPT中至少出現一次。
d:刪除模式空間中匹配到的內容 Delete pattern space
a \text 在行後面插入文本「text」,支持使用\n實現多行插入
Append text, which has each embedded newline preceded by a back slash.
i \text 在行前面插入文本「text」,支持使用\n實現多行插入
Insert text, which has each embedded newline preceded by a back slash.
c \text 把匹配到的行替換爲此處指定的文本「text」
Replace the selected lines with text, which has each embedded new line preceded by a backslash.
w filename 保存模式空間匹配的行至指定的文件中
Write the current pattern space to filename.
r filename 讀取指定文件內容至當前文件被模式匹配到的行文件後合併
Append text read from filename.
= : 爲模式匹配到的行打印行號 Print the current line number.
!: 條件取反(它比較特殊,它必須跟其餘編輯命令一塊兒使用)
s/regexp/replacement/ : 查找替換,其分隔符可自行指定,經常使用有s@@@,s###
它有一個特殊的用法s//x&/:表示將被查找的內容在其前面添加x內容
s//&x/:表示將被查找的內容在其後面添加x內容
&表明被查找的內容
[root@localhost test]# cat cat1 hi,everyone now I will show how to use cat [root@localhost test]# sed 's/e/&#/' cat1 hi,e#veryone now I will show how to use# cat [root@localhost test]# sed 's/e/#&/' cat1 hi,#everyone now I will show how to us#e cat
p :顯示替換成功的行
g :全局替換
w filename : 將替換成功的結果保存至指定文件中
查找替換在sed中應用很廣,下面不少例子都是以sed的替換功能實現的
p :顯示當前模式空間中的內容 Print the current pattern space.
注:同時使用多個編輯命令,命令之間要用;隔開(!除外)
例子以下:
[root@localhost test]# sed 'p;=' cat1 hi,everyone 1 hi,everyone now I will show how to use cat 2 now I will show how to use cat
實例演示:
一、刪除/etc/grub2.conf文件中全部以空白開頭的行行首的空白字符
sed 's#^[[:space:]]\+##' /etc/grub2.cfg
這裏##是將前面匹配到的內容刪除的意思,上面文本內容太多,就不截取了。
二、刪除/etc/fstab文件中全部以#開頭,後面至少跟一個空白字符的行的行首的#號及#後面的全部空白字符
sed 's@^#[[:space:]]\+@@' /etc/fstab
[root@localhost test]# cat /etc/fstab # # /etc/fstab # Created by anaconda on Tue Jul 19 23:52:41 2016 # # 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/centos-root / xfs defaults 0 0 UUID=6efb8a23-bae1-427c-ab10-3caca95250b1 /boot xfs defaults 0 0 /dev/mapper/centos-swap swap swap defaults 0 0 [root@localhost test]# sed 's@^#[[:space:]]\+@@' /etc/fstab # /etc/fstab Created by anaconda on Tue Jul 19 23:52:41 2016 # 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/centos-root / xfs defaults 0 0 UUID=6efb8a23-bae1-427c-ab10-3caca95250b1 /boot xfs defaults 0 0 /dev/mapper/centos-swap swap swap defaults 0 0
三、在/etc/fstab每一行行首增長#號
cat /etc/fstab # # /etc/fstab # Created by anaconda on Tue Jul 19 23:52:41 2016 # # 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/centos-root / xfs defaults 0 0 UUID=6efb8a23-bae1-427c-ab10-3caca95250b1 /boot xfs defaults 0 0 /dev/mapper/centos-swap swap swap defaults 0 0 sed 's@^@#&@' /etc/fstab # ## ## /etc/fstab ## Created by anaconda on Tue Jul 19 23:52:41 2016 ## ## 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/centos-root / xfs defaults 0 0 #UUID=6efb8a23-bae1-427c-ab10-3caca95250b1 /boot xfs defaults 0 0 #/dev/mapper/centos-swap swap swap defaults 0 0
四、處理/etc/fstab路徑,使用sed命令取出其目錄名和基名
目錄名:
[root@localhost test]# echo '/etc/fstab' | sed -r 's#(.*/)([^/]+/?)#\1#' /etc/
基名:
[root@localhost test]# echo '/etc/fstab' | sed -r 's#(.*/)([^/]+/?)#\2#' fstab
sed高級編輯命令:
h:把模式空間中的內容覆蓋至保持空間中;
H:把模式空間中的內容追加至保持空間中;
g:把保持空間中的內容覆蓋至模式空間中;
G:把保持空間中的內容追加至模式空間中;
x:把模式空間中的內容與保持空間中的內容互換;
n:覆蓋讀取匹配到的行的下一行至模式空間中;
N:追加讀取匹配到的行的下一行至模式空間中;
d:刪除模式空間中的行;
D:刪除多行模式空間中的全部行;
我知道看了上面這些高級命令必定很暈,下面經過5個例子來理一下使用sed高級編輯命令的思路
高級編輯命令實例演示:
一、 sed -n 'n;p' FILE:
''內意思:將讀取到的行的下一行內容顯示至模式空間
-n 'p':將模式空間中被匹配到的內容顯示至屏幕
兩者結合起來就是隻顯示偶數行。
[root@localhost test]# cat -n cat1 1 hi,everyone 2 now I will show how to use cat [root@localhost test]# sed -n 'n;p' cat1 now I will show how to use cat
2、 sed '1!G;h;$!d' FILE:
這個命令按'x;x;x'中的;號分割分爲三部分:
一、1!G:除讀取的第一行都進行G編輯
二、h:將模式空間中的內容覆蓋至保持空間中
三、$!d:刪除非最後一行的內容
命令解釋完了,我想你們對此應該仍是一頭霧水,那麼就具體說明這個命令的意思:
1)讀取文本信息的1行內容至模式空間,因爲是第一行因此模式空間中的1行不進行G操做,以後觸發h,將模式空間中的1行放入保持空間中,再以後觸發$!d,因爲1行不是最後一行,因此將模式空間中的1行刪除;
2)讀取2行內容至模式空間,因爲不是1行因此觸發G操做,將保持空間中1行追加到2行後面,此時模式空間中的順序內容爲2行,1行,以後h命令將模式空間中內容覆蓋至保持空間中,此時保持空間內容爲2行,1行,由於2行不是最後一行,因此$!d刪除模式空間中內容;
3)上述過程不斷重複,直到最後一行時不進行d操做,此時模式空間中的第一行就是原文件的最後一行。
所以這個命令就是原文件內容反過來的排列。
[root@localhost test]# cat cat1 hi,everyone now I will show how to use cat [root@localhost test]# sed '1!G;h;$!d' cat1 now I will show how to use cat hi,everyone
三、 sed '$!d' FILE:
通過了上面兩個命令的磨練,這個就顯得簡單了。
'$!d':不是最後一行則刪除
意思是說模式空間中只保留文本的最後一行
[root@localhost test]# sed '$!d' cat1 now I will show how to use cat
四、 sed '/^$/d;G' FILE
'/^$/d':查找模式空間中的每行是否包含空白行,若包含則將其刪除
G:將保持空間中的內容追加至模式空間中的每行後面
刪除原有的全部空白行,然後爲全部的非空白行後添加一個空白行;
兩者結合在一塊兒即:保證指定文件每一行後方有且只有一個空白行
[root@localhost test]# sed '/^$/d;G' cat1 hi,everyone now I will show how to use cat
五、 sed 'n;d' FILE:顯示奇數行;
這個就很簡單了,你們按照sed的工做原理及編輯命令n與d很容易就能明白其所表達的意思
[root@localhost test]# cat cat1 hi,everyone now I will show how to use cat [root@localhost test]# sed 'n;d' cat1 hi,everyone
學習sed的一些感覺
學習sed若是對於sed的編輯命令或高級命令很困惑,那麼不妨試試照着我上面的sed工做流程圖,一步一步的本身畫圖分析每一步所表明的意思。這既能增強本身對sed這個工具的瞭解也可有助於理清咱們的使用思路。這是我在學習過程當中以爲頗有用的一種方法。
sed這個工具它的精髓在於它的替換,替換的精髓在於精確匹配,而精確匹配又離不開正則表達式的,因此若是以爲本身對於替換很不擅長的話那麼能夠好好練習一下正則表達式。
sed是一個實用性很強的文本編輯工具,因爲能力所限,也只能對sed進行下簡要的介紹,你們若對其有進一步的興趣能夠查找更專業的書籍。