何爲sed
sed
是Stream Editor的簡稱,是Linux自帶的一個文本處理工具,以行爲單位,對文本進行處理,可以對每行的內容做替換、刪除、新增、選取等操作。
sed
在處理文本時,會把當前行讀入到緩衝區,這個緩衝區稱爲模版塊(Pattern Space),然後用相關命令處理模板塊的內容,處理完成後,將緩衝區的內容輸出,直到文件末尾。此外sed
也提供了臨時緩衝區(Hold Space),用於實現更加複雜的文本操作。
sed
命令行格式爲:
sed [option]... {script-only-if-no-other-script} [input-file]...
option
爲選項,後面接命令,再後面接輸入文件。
命令
sed
單個命令的語法爲:
[n1[,n2]]<function>
n1
和n2
可選,代表選擇進行function
操作的前置條件,n1
和n2
有多種取值方式:
- 當取值爲數字或
$
時,代表行號的限定範圍,$
表示最後一行,例如:
從第10行開始,進行function
操作,直到第20行,那麼可以寫爲:10,20<function>
從第10行開始,進行function
操作,可以寫爲:10<function>
或10,$<function>
從第1行開始,進行function
操作,直到第10行,可以寫爲:1,10
- 當取值爲正則表達式時,代表行需要滿足正則表達式纔會進行
function
的相關操作,例如:
從第10行開始,對不以Hello
開頭的行進行function
操作,可以寫爲10,/^Hello/<function>
- 當取值爲包含
!
時,表示在一定條件下不執行相關操作,例如:
不對第1到4行的文本執行function
操作,可以寫爲:1,5!<function>
此外sed
可以接受多個命令,可以用;
隔開,或者用多個-e
選項即可,在處理模版塊時會按照先後依次順序執行。
在介紹function
之前,爲了方便演示,可以新建一個文件testfile
,並寫入以下內容:
Line 1
Line 2
...
Line 10
或者使用Shell自動生成:
echo > testfile
for i in {1..10}
do
echo "Line $i" >> testfile
done
基本function
的種類:
-
a
:在當前行下面插入文本。
後面可以接字符串,這個字符串會插入到當前行的下一行,例如在第8行後插入字符串helloworld
:sed '8ahelloworld' testfile
或者從第8行開始,在每行後面插入一個
helloworld
sed '8,$a helloworld',
-
i
:在當前行上面插入文本
類似於a
,後面接字符串,這個字符串會插入到當前行的上一行,例如在第8行之前插入字符串helloworld
:sed '8ihelloworld' testfile
-
c
:把當前的行替換爲新的文本
例如把第八行的Line 8
替換爲helloworld
:sed '8chelloworld' testfile
-
d
:刪除當前的行
例如刪除第八行的文本Line 8
刪除:sed '8d' testfile
或者刪除第5到第8行文本:
sed '5,8d' testfile
刪除包含字符串
Line 8
的行:sed '/Line 8/d' testfile
-
s
:替換指定的字符串,語法規則如下:sed 's/Regexp/Replacement/Flags' file
s
命令將符合正則表達式Regexp
的行全部替換成Replacement
,最後的字符Flags
爲標誌選項,有以下幾種:g
:用Replacement
替換模版空間中所有匹配Regexp
的部分,則不僅僅是第一個匹配部分
例如要將testfile
中的單詞Line
全部替換成Word
,那麼可以寫作:sed 's/Line/Word/g' testfile
- 1到9的數字
N
:只用Replacement
替換模版空間中,忽略第0
到N - 1
個匹配Regexp
的部分,然後將匹配Regexp
的部分輸出。
例如,下面案例會將Line
替換爲Lixx
:sed 's/[a-z]/x/2g' testfile
p
:若發生了替換操作,則輸出模版空間中修改後的行數據,和p
命令很類似w file-path
:若發生了替換操作,將模板塊中的數據寫入到文件file-path
中
例如下面示例會將從第5行開始,替換Line
爲Word
,並將替換後的結果輸出到當前目錄的outputfile
文件,直到文件末尾:sed -n '5,$s/Line/Word/gw outputfile' testfile
i
:與Regexp
匹配時,不區分大小寫
例如,下面命令可以將Line
替換成Word
:sed 's/line/Word/ig' testfile
此外,也可利用
s
在每行頭部或者尾部添加字符串,可以利用字符^
表示行頭,字符$
表示行尾
比如在每行行頭添加單詞Hello
:sed 's/^/Hello/g' testfile
在行尾添加單詞
Hello
:sed 's/$/Hello/g' testfile
當然
s
前面也可以加上行範圍 -
p
:打印當前模板塊空間的所有內容(模板塊的定義前面已經提到),並追加到默認輸出之後
例如在每行後面追加一個單詞number
,並將修改前和修改後的結果打印出來(-n
表示不打印默認輸出):sed -n 'p;s/$/number/g;p' testfile
或者從第8行開始,將以
Line
開頭的行打印出來sed '5,/Line/p' testfile
其他function
種類:
-
n
:讀取下一個輸入行,用下一個命令處理新的行而不是使用第一個命令 -
N
:追加下一個輸入行到模板塊的後面並在中間嵌入一個新行,可以利用該命令將多個行的內容整合爲一行。
例如下列命令可以將三行語句整合爲一行:sed 'N;N;s/\n/ /g' testfile
邏輯就是就是讀取三行後,然後將換行符
\n
替換爲空格。
或者可以輸出行號爲奇數的行:sed -n '$!N;P' testfile
-
P
:打印當前模板塊空間的第一行
模板塊和臨時緩衝區(Hold Space)的操作:
h
:拷貝模板塊的內容到臨時緩衝區H
:追加模板塊的內容到臨時緩衝區D
:刪除模板塊的第一行(意味着這個被刪除的部分不會傳至標準輸出),並放棄之後的命令,然後對新讀入的內容,重頭執行sed
。g
:取得臨時緩衝區的內容,並替換當前模板塊中的文本G
:取得臨時緩衝區的內容,並追加到當前模板塊中文本的後面
可以利用sed
的臨時緩衝區執行更加複雜的文本修改操作,舉一個經典的例子:
實現倒序輸出,即從最後一行開始逐行輸出到第一行
思路:要實現倒序輸出,我們需要在讀取每一行的時候,就將行的內容放在模板塊的前面。所以在讀第一行的時候,需要將第一行的文本從模式塊讀到臨時緩衝區,然後再讀第二行的時候,把臨時緩衝區中第一行的數據追加到模版塊,依次類推。只需要對第一行和最後一行的做特殊處理即可。
sed '1!G;h;$!d' testfile
1!G
表示不對第一行做G
操作,$!d
表示不對最後一行做d
操作
執行過程示例圖:
其他操作:
I
:列出不能打印字符的清單q
:退出sed
選項
option
參數主要包含以下幾個:
-n
或--quiet
或--silent
:僅顯示被sed
特殊處理的行,如果不加,那麼所有來自輸入文本的數據都會被輸出,不論有沒有進行過修改。-e <script>
或--expression=<script>
:使用script
,也可以省略掉-e
-f <script-file>
或--file=script-file
:指定存放script
的文件-i[suffix]
或--in-place[=suffix]
:如果不加suffix
,那麼直接修改文件的內容,不輸出到終端。如果加了suffix
,則會在處理前,對文件進行備份(複製),備份文件名會在原先文件名後面加上suffix
,然後再對原文件進行修改-l <number>
或--line-length=<number>
:--posix
:禁用的GNU擴展功能,例如replacement
選項中中的\L
、\l
、\U
、\u
、\E
。-r
或--regexp-extended
:讓sed
支持擴展的正則表達式-s
或--separate
:在處理多個文件時,對它們依次單獨處理,而不是視爲一個整體-u
或--unbuffered
:從輸入文件中加載儘可能少的行,並更頻繁地刷新輸出緩衝區,適合機器內存比較緊張的情況-z
或--null-data
:每行按照\0
分隔,而不是換行符。--help
:查看sed
幫助--version
:查看sed
版本