Shell 三劍客之 sed
1. Sed 概述
1.1 Sed 是什么
Sed 全名為 Stream EDitor,顧名思義是對數(shù)據(jù)流進行編輯操作的一個命令,它能夠遍歷文件或文件流,對讀入的輸入流可以將其先存儲在模式空間中,并將行號記錄在內(nèi)存中,利用模式空間中的一系列指定命令對其進行操作,待操作完成后從模式空間輸出到 stdout,類似于在一個管道在其中對數(shù)據(jù)進行加工,完成后從另一頭輸出,接著讀取下一行,重復往返,直至將所有標準輸入讀取處理完成。
1.2 為什么用 Sed
Sed 相較于 grep/awk,其主要功能為對文件進行修改處理,可以對文件或標準輸入數(shù)據(jù)流進行增刪改查等操作,尤其適用于大文件或有規(guī)律的文件,利用此工具,能夠幫助我們快捷的在編寫 Shell 腳本中得心應手的對文件進行操作。
2. Sed 的適用場景
-
超大文件處理;
-
有規(guī)律的文本,例如格式化后的日志文件等;
-
對文件進行批量增加,替換等。
3. Sed 的處理模式
Sed 對輸入的一行數(shù)據(jù)進行處理的模式,對整個文件進行重復執(zhí)行此模式處理,在此說明對輸入的一行數(shù)據(jù)處理的內(nèi)在機制如下圖所示:

-
首先讀入文件流的一行到模式空間;
-
在模式空間內(nèi),對內(nèi)容進行模式匹配處理;
-
輸出處理后的數(shù)據(jù)內(nèi)容;
-
清空當前模式空間;
-
讀取第二行輸入流到模式空間;
-
又開始對模式空間內(nèi)的下一行輸入數(shù)據(jù)進行處理。
4. 語法詳解
sed 語法格式如下圖所示:

sed [option] 'address command' [file …]
sed 的語法格式主要分為四個字段,options 選項,引號內(nèi)有地址定界 / 命令,以及要處理的文件,接下來讓我們詳細講解每一個語法字段,更全面的認識 sed 這個腳本利器。
4.1 options:
選項為可選,利用它來為 sed 指定一些處理方式,主要的有如下:
- -n: 靜默模式,我們知道 sed 默認處理完模式空間后將內(nèi)容輸出到標準輸出,利用這個這個參數(shù)僅顯示 script 處理后的結(jié)果,不再默認顯示模式空間中的內(nèi)容,例如:打印 /etc/passwd 的第三行
[root@shell workspace]# sed -n '3p' /etc/passwd
daemon:x:2:2:daemon:/sbin:/sbin/nologin
在此直接指定地址定界 3,然后 command 為 p 打印輸出,由于不想輸出 /etc/passwd 的全部內(nèi)容,因此添加了 - n 選項。
* -e:<script>或--expression=<script> 以選項中指定的script來處理輸入的文本文件,可以同時執(zhí)行多個腳本;
* -f:對制定的文件直接進行sed的command操作;
* -i:直接修改原文件,我們都知道sed默認不對文件進行修改,只是讀入一行到模式空間中,處理完成后輸出,此參數(shù)為也直接修改了源文件;
* -r:支持擴展正則表達式,而不是使用默認的基礎(chǔ)正則表達式。類比grep命令的egrep,更加快捷簡潔的使用擴展正則表達式,因為有些元字符不用再使用反斜線"\\"了。
4.2 address:
地址定界用來指定讀入文件的邊界或步長。
startline,endline
:指定讀入文件的開始行于結(jié)束行號。/regexp/
: 利用正則表達式匹配到的行進行處理,例如:打印 /etc/passwd 從以 root 開始到 sync 結(jié)束的內(nèi)容
[root@shell workspace]# sed -n '/^root/,/^sync/p' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
在此利用了匹配元字符 ^
用來匹配行首,此內(nèi)容在正則表達式中已經(jīng)進行了詳細解釋。
/pattern1/,/pattern2/
: 第一次被 pattern1 匹配到的行開始,直到被 pattern2 匹配到的行結(jié)束,例如:打印 /etc/passwd 的第四行到第七行的內(nèi)容
[root@shell workspace]# sed -n '3,7p' /etc/passwd
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
linenuber
: 直接指定行號,需要處理哪一行。startline,+n
: 從那一行開始,往后 n 行結(jié)束,例如:打印 /etc/passwd 的從第三行開始往后的 2 行的內(nèi)容
[root@shell workspace]# sed -n "3,+2p" /etc/passwd
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
startline~step
: 指定步長,每隔 step 步進行處理,常用在奇偶數(shù)處理,例如:打印奇數(shù)行
seq 10 |sed -n '1~2p'
seq 來輸出以數(shù)字為內(nèi)容的 10 行,然后利用 ~2
作為步長打印輸出。
4.3 command:
具體對指定的文件進行怎樣的處理,例如對模式空間內(nèi)的內(nèi)容進行增刪改查具體的操作。
4.3.1 增
- i:insert,在制定或匹配到的行前面添加新行內(nèi)容為 string,
i\string
,
為 /etc/passwd 中的第一行前面添加一行內(nèi)容為 "####",例如:
[root@shell workspace]# sed '1i####' /etc/passwd
####
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
.....
- a:append,在指定或匹配到的行后面追加新行,內(nèi)容為 string,
a\string
。
為 /etc/passwd 的第一行后面添加內(nèi)容 "aaa",例如:
[root@shell workspace]# sed '1a###' /etc/passwd
root:x:0:0:root:/root:/bin/bash
###
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
4.3.2 刪
- d:delete,刪除符合地址定界條件的的行
刪除 /etc/inittab 文件中注釋行,例如:
sed '/^#/d' /etc/inittab
直接利用元字符匹配鉚定以#
開頭的行進行刪除操作,注意此處沒有直接修改文件,如果添加 -i
選項,則直接對源文件進行修改,一般需要先備份,然后操作以免誤操作原始文件。
4.3.3 改
- s:
s/pattern/string/修飾符
: 查找并替換,默認只替換每行中第一次被模式匹配到的字符串 ,如果修飾符為 g, 則為全部替換。
替換 /etc/passwd 中的 root 為大寫,例如:
[root@shell workspace]# sed 's/root/ROOT/g' /etc/passwd
ROOT:x:0:0:ROOT:/ROOT:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
...
替換 /etc/inittab 文件中 "id:3:initdefault:" 一行中的數(shù)字為 5,例如:
sed 's/id:[0-9]/id:5/g' /etc/inittab
在此利用元字符匹配 [0-9] 的一個數(shù)字進行替換為 id:5
。
4.3.4 查
- p:print,默認 sed 對模式空間內(nèi)的處理完畢后,將輸出的結(jié)果輸出在標準輸出,添加 p 命令,相當于輸出了原文,又一次輸出了模式匹配處理后的內(nèi)容。
打印 /etc/passwd 的第三行,指定行號,例如:
[root@shell workspace]# sed -n '3p' /etc/passwd
daemon:x:2:2:daemon:/sbin:/sbin/nologin
在此直接指定地址定界 3,然后 command 為 p 打印輸出,由于不想輸出 /etc/passwd 的全部內(nèi)容,因此添加了 - n 選項。
5. 實例
5.1 需求
目前騰訊云服務器 Ubuntu 版本用戶為 ubuntu 用戶,現(xiàn)又 1000 臺服務器需要去開啟 root 遠程登錄。
5.2 思路
開啟 ubuntu 服務器的遠程登錄即修改其的 /etc/ssh/sshd_config 文件的 prohibit-password 為 yes 即可,重啟 sshd 服務即可,利用腳本邏輯處理。
5.3 實現(xiàn)
核心利用 sed 代碼:
if [ ${ostype} == 'Ubuntu' ];then
sed -i 's/prohibit-password/yes/g' /etc/ssh/sshd_config
# 重啟ssh服務
service sshd restart
[ $? -eq 0] && echo "${OSTYPE} sshd 開啟成功" >>${LOG_FILE}
fi
6. 注意事項
- sed 中利用于正則表達式配合可以得到 1+1 大于二的效果,配合使用功能更加豐富強大;
- sed 常用于修改文件,如果為查詢文件可以利用 grep,因為 grep 檢索文件效率最高,如果為格式化輸出建議使用 awk;
- sed 在修改文件的時候盡可能先不要添加
-i
options,以免將源始文件修改異常難以恢復。
7. 小結(jié)
sed 的功能非常強大,它是我們 shell 編程中對文件修改不可或缺的利器,配合正則表達式常用來批量修改大文件,或有一定格式規(guī)律的文件,其還有很多高級功能。如果學有余力建議去 man 手冊詳細學習查看,在利用 sed 工具的時候需要時刻腦海中牢記求語法格式,萬變不離其宗,遵循語法舉一反三能夠達到學生事半功倍的效果。