sed基本用法 sed文字塊處理 、 sed高階應用 總結和答疑
NSD SHELL DAY05
1 案例1:sed基本用法
1.1 問題
本案例要求熟悉sed命令的p、d、s等常見操作,並結合正則表示式,完成以下任務:
- 刪除檔案中每行的第二個、最後一個字元
- 將檔案中每行的第一個、第二個字元互換
- 刪除檔案中所有的數字
- 為檔案中每個大寫字母新增括號
1.2 方案
sed文字處理工具的用法:
- 用法1:前置命令 | sed [選項] '條件指令'
- 用法2:sed [選項] '條件指令' 檔案.. ..
相關說明如下:
- 條件可以是行號或者/正則/
- 沒有條件時,預設為所有條件
- 指令可以是增、刪、改、查等指令
- 預設sed會將所有輸出的內容都打印出來,可以使用-n遮蔽預設輸出
- 選項中可以使用-r選項,讓sed支援擴充套件正則
1.3 步驟
實現此案例需要按照如下步驟進行。
步驟一:認識sed工具的基本選項
sed命令的常用選項如下:
-n(遮蔽預設輸出,預設sed會輸出讀取文件的全部內容)
-r(讓sed支援擴充套件正則)
-i(sed直接修改原始檔,預設sed只是通過記憶體臨時修改檔案,原始檔無影響)
1)sed命令的 -n 選項
執行p列印等過濾操作時,希望看到的是符合條件的文字。但不使用任何選項時,預設會將原始文字一併輸出,從而干擾過濾效果。比如,嘗試用sed輸出/etc/hosts的第1行:
- [[email protected] ~]# sed '1p' /etc/hosts
- 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
- 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
- ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
可以發現所有的行都被顯示出來了(第1行重複2次)。—— 正確的用法應該新增 -n 選項,這樣就可以只顯示第1行了:
- [[email protected] ~]# sed -n '1p' /etc/hosts
- 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
行號可以是連續的行號,如列印passwd第3到第6行賬戶的資訊:
- [[email protected] ~]# sed -n '3,6p' /etc/passwd
- 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
2)sed命令的 -i 選項
正常情況下,sed命令所做的處理只是把操作結果(包括列印、刪除等)輸出到當前終端螢幕,而並不會對原始檔案做任何更改:
- [[email protected] ~]# sed 'd' /etc/passwd //刪除所有行
- [[email protected] ~]# cat /etc/passwd //檢視原始文字,並未改動
若希望直接修改檔案內容,應新增選項 -i 。
比如,直接刪除test.txt(自行建立一個任意內容的檔案)的第1~4行:
- [[email protected] ~]# sed -i '1,4d' test.txt //刪除操作
- [[email protected] ~]# cat test.txt //確認刪除結果
下文中關於使用sed修改檔案的示例中,為了避免大家在練習過程中因誤操作導致系統故障,命令省略 –i 選項,不再逐一說明。需要時,大家可自行加上此選項。
3)多個指令可以使用分號隔離
用分號來隔離多個操作,比如:
- [[email protected] ~]# sed -n '1p;4p' /etc/passwd
- root:x:0:0:root:/root:/bin/bash
- adm:x:3:4:adm:/var/adm:/sbin/nologin
步驟二:認識sed工具的條件
# sed [選項] '條件指令' 檔案.. ..
sed命令可以使用行號或正則做為條件匹配:
1)行號案例
列印第3行:
- [[email protected] ~]# sed -n '3p' /etc/passwd
列印第3到5行:
- [[email protected] ~]# sed -n '3,5p' /etc/passwd
列印第3和5行:
- [[email protected] ~]# sed -n '3p;5p' /etc/passwd
列印第3以及後面的10行:
- [[email protected] ~]# sed -n '3,+10p' /etc/passwd
列印奇數行:
- [[email protected] ~]# sed -n '1~2p' /etc/passwd
列印偶數行:
- [[email protected] ~]# sed -n '2~2p' /etc/passwd
2)正則案例
列印包含root的行:
- [[email protected] ~]# sed -n '/root/p' /etc/passwd
列印bash結尾的行:
- [[email protected] ~]# sed -n '/bash$/p' /etc/passwd
3)沒有條件,則表示匹配所有行
- [[email protected] ~]# sed -n 'p' /etc/passwd
步驟三:sed工具的p、d、s操作指令案例集合
1)下面看看sed工具的p指令案例集錦(自己提前生成一個a.txt檔案)
- [[email protected] ~]# sed -n 'p' a.txt //輸出所有行,等同於cat a.txt
- [[email protected] ~]# sed -n '4p' a.txt //輸出第4行
- [[email protected] ~]# sed -n '4,7p' a.txt //輸出第4~7行
- [[email protected] ~]# sed -n '4,+10p' a.txt //輸出第4行及其後的10行內容
- [[email protected] ~]# sed -n '/^bin/p' a.txt //輸出以bin開頭的行
- [[email protected] ~]# sed -n '$=' a.txt //輸出檔案的行數
2)下面看看sed工具的d指令案例集錦(自己提前生成一個a.txt檔案)
- [[email protected] ~]# sed '3,5d' a.txt //刪除第3~5行
- [[email protected] ~]# sed '/xml/d' a.txt //刪除所有包含xml的行
- [[email protected] ~]# sed '/xml/!d' a.txt //刪除不包含xml的行,!符號表示取反
- [[email protected] ~]# sed '/^install/d' a.txt //刪除以install開頭的行
- [[email protected] ~]# sed '$d' a.txt //刪除檔案的最後一行
- [[email protected] ~]# sed '/^$/d' a.txt //刪除所有空行
3)sed命令的s替換基本功能(s/舊內容/新內容/選項):
- [[email protected] ~]# vim test.txt //新建素材
- 2017 2011 2018
- 2017 2017 2024
- 2017 2017 2017
- [[email protected] ~]# sed 's/2017/xxxx/' test.txt
- [[email protected] ~]# sed 's/2017/xxxx/g' test.txt
- [[email protected] ~]# sed 's/2017/xxxx/2' test.txt
- [[email protected] ~]# sed 's/2017//2' test.txt
- [[email protected] ~]# sed -n 's/2017/xxxx/p' test.txt
4)下面看看sed工具的s指令案例集錦(自己提前生成一個a.txt檔案)
注意:替換操作的分隔“/”可改用其他字元,如#、&等,便於修改檔案路徑
- [[email protected] ~]# sed 's/xml/XML/' a.txt //將每行中第一個xml替換為XML
- [[email protected] ~]# sed 's/xml/XML/3' a.txt //將每行中的第3個xml替換為XML
- [[email protected] ~]# sed 's/xml/XML/g' a.txt //將所有的xml都替換為XML
- [[email protected] ~]# sed 's/xml//g' a.txt //將所有的xml都刪除(替換為空串)
- [[email protected] ~]# sed 's#/bin/bash#/sbin/sh#' a.txt //將/bin/bash替換為/sbin/sh
- [[email protected] ~]# sed '4,7s/^/#/' a.txt //將第4~7行註釋掉(行首加#號)
- [[email protected] ~]# sed 's/^#an/an/' a.txt //解除以#an開頭的行的註釋(去除行首的#號)
步驟四:利用sed完成本例要求的任務
參考資料檔案內容如下:
- [[email protected] ~]# cat nssw.txt
- Hello the world
- ni hao ma beijing
本小節的操作使用nssw.txt作為測試檔案。
1)刪除檔案中每行的第二個、最後一個字元
分兩次替換操作,第一次替換掉第2個字元,第二次替換掉最後一個字元:
- [[email protected] ~]# sed 's/.//2 ; s/.$//' nssw.txt
2)將檔案中每行的第一個、倒數第1個字元互換
每行文字拆分為“第1個字元”、“中間的所有字元”、“倒數第1個字元”三個部分,然後通過替換操作重排順序為“3-2-1”:
- [[email protected] ~]# sed -r 's/^(.)(.*)(.)$/\3\2\1/' nssw.txt
3)刪除檔案中所有的數字
因原檔案內沒有數字,行首也沒有空格,這裡稍作做一點處理,生成一個新測試檔案:
- [[email protected] ~]# sed 's/[0-9]//' nssw.txt
以nssw2.txt檔案為例,刪除所有數字、行首空格的操作如下:
- [[email protected] ~]# sed -r 's/[0-9]//g;s/^( )+//' nssw2.txt
4)為檔案中每個大寫字母新增括號
使用“()”可實現保留功能,所以可參考下列操作解決:
- [[email protected] ~]# sed -r 's/([A-Z])/[\1]/g' nssw.txt
2 案例2:使用sed修改系統配置
2.1 問題
本案例要求熟悉課上的sed應用案例,並編寫指令碼anonftp.sh,實現以下功能:
- 通過yum安裝vsftpd軟體包
- 修改vsftpd服務配置,開啟匿名上傳
- 調整/var/ftp/pub目錄許可權,允許寫入
- 啟動vsftpd服務,並設定開機自執行
2.2 步驟
實現此案例需要按照如下步驟進行。
步驟一:編寫anonftp.sh指令碼,用來裝配匿名FTP服務
1)任務需求及思路分析
vsftpd服務的安裝、改目錄許可權、起服務等操作可以直接寫在指令碼中。
修改vsftpd.conf配置的工作可以使用sed命令,根據預設配置,只需要定位到以#anon開頭的行,去掉開頭的註釋即可。
2)根據實現思路編寫指令碼檔案
- [[email protected] ~]# vim anonftp.sh
- #!/bin/bash
- yum -y install vsftpd //安裝vsftpd軟體
- cp /etc/vsftpd/vsftpd.conf{,.bak} //備份預設的配置檔案
- sed -i "s/^#anon/anon/" /etc/vsftpd/vsftpd.conf //修改服務配置
- chmod 777 /var/ftp/pub //調整目錄許可權
- systemctl start vsftpd //啟動服務
- systemctl enable vsftpd //設為自動執行
- [[email protected] ~]# chmod +x anonftp.sh
- [[email protected] ~]# ./anonftp.sh
3 案例3:sed多行文字處理
3.1 問題
本案例要求使用sed工具來完成下列任務操作:
- 修改主機名配置檔案
- 修改hosts檔案,新增兩條對映記錄:192.168.4.5 與 svr5.tarena.com、svr5,還有119.75.217.56與www.baidu.com
3.2 方案
# sed [選項] '條件指令' 檔案..
sed工具的多行文字處理操作:
- i: 在指定的行之前插入文字
- a:在指定的行之後追加文字
- c:替換指定的行
3.3 步驟
基本語法格式案例:
注意:系統預設沒有a.txt檔案,需要自己建立一個測試檔案!!!
- [[email protected] ~]# sed '2a XX' a.txt //在第二行後面,追加XX
- [[email protected] ~]# sed '2i XX' a.txt //在第二行前面,插入XX
- [[email protected] ~]# sed '2c XX' a.txt //將第二行替換為XX
實現此案例需要按照如下步驟進行。
步驟一:修改主機名配置檔案
1)確認修改前的配置
- [[email protected] ~]# cat /etc/hostname
- svr5.tarena.com
2)使用sed修改主機名配置所在行的內容(c整行替換)
- [[email protected] ~]# sed '1c mysvr.tarena.com' /etc/hostname
步驟二:修改hosts檔案,新增新的記錄
1)確認修改前的配置
- [[email protected] ~]# cat /etc/hosts
- 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
- ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
2)使用sed修改hosts檔案,新增兩行新紀錄(a追加)
- [[email protected] ~]# sed -i '$a 192.168.4.5 svr5.tarena.com svr5' /etc/hosts
- 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
- ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
- 192.168.4.5 svr5.tarena.com svr5
4 案例4:sed綜合指令碼應用
4.1 問題
本案例要求編寫指令碼getupwd.sh,實現以下需求:
- 找到使用bash作登入Shell的本地使用者
- 列出這些使用者的shadow密碼記錄
- 按每行“使用者名稱 --> 密碼記錄”儲存到getupwd.log,如圖-1所示
圖-1
4.2 方案
基本思路如下:
- 先用sed工具取出登入Shell為/bin/bash的使用者記錄,儲存為臨時檔案/tmp/urec.tmp,並計算記錄數量
- 再結合while迴圈遍歷取得的賬號記錄,逐行進行處理
- 針對每一行使用者記錄,採用掐頭去尾的方式獲得使用者名稱、密碼字串
- 按照指定格式追加到/tmp/getuupwd.log檔案
- 結束迴圈後刪除臨時檔案,報告分析結果
4.3 步驟
實現此案例需要按照如下步驟進行。
步驟一:編寫getupwd.sh指令碼
- [[email protected] ~]# vim ./getupwd.sh
- #/bin/bash
- A=$(sed -n '/bash$/s/:.*//p' /etc/passwd) ## 提取符合條件的賬號記錄
- for i in $A ##遍歷賬號記錄
- do
- pass1=$(grep $i /etc/shadow)
- pass2=${pass1#*:}
- pass=${pass2%%:*}
- echo "$i --> $pass"
- done
- [[email protected] ~]# chmod +x ./getupwd.sh
步驟二:測試、驗證執行結果
- [[email protected] ~]# ./getupwd.sh
- 使用者分析完畢,請查閱檔案 /tmp/getupwd.log
- [[email protected] ~]# less /tmp/getupwd.log
- root --> $6$IWgMYmRACwdbfwBo$dr8Yn983nswiJVw0dTMjzbDvSLeCd1GMYjbvsDiFEkL8jnXOLcocBQypOCr4C6BRxNowIxjh6U2qeFU0u1LST/
- zengye --> $6$Qb37LOdzRl5995PI$L0zTOgnhGz8ihWkW81J.5XhPp/l7x2./Me2ag0S8tRndCBL9nIjHIKkUKulHxJ6TXyHYmffbVgUT6pbSwf8O71
- clamav --> !!
- mysql --> !!
- abc --> !!
- .. ..
從上述參考指令碼可以發現,使用sed來實現欄位提取會比較複雜。下一章課程將會學到awk命令,屆時可以通過更簡單的方法來改進此指令碼內容。
總結知識點:
#sed [選項] '條件指令' 檔案
選項:
-n 遮蔽預設輸出
-r 支援擴充套件正則
-i 修改原始檔
條件:
行號 4 4,5 4~2 4,+10
/正則/
指令:
p 列印
d 刪除
s 替換s/舊/新/g
a 追加
i 插入
c 替換行