1. 程式人生 > >sed基本用法 sed文字塊處理 、 sed高階應用 總結和答疑

sed基本用法 sed文字塊處理 、 sed高階應用 總結和答疑

Top

NSD SHELL DAY05

  1. 案例1:sed基本用法
  2. 案例2:使用sed修改系統配置
  3. 案例3:sed多行文字處理
  4. 案例4:sed綜合指令碼應用

1 案例1:sed基本用法

1.1 問題

本案例要求熟悉sed命令的p、d、s等常見操作,並結合正則表示式,完成以下任務:

  • 刪除檔案中每行的第二個、最後一個字元
  • 將檔案中每行的第一個、第二個字元互換
  • 刪除檔案中所有的數字
  • 為檔案中每個大寫字母新增括號

1.2 方案

sed文字處理工具的用法:

 
  1. 用法1:前置命令 | sed [選項] '條件指令'
  2. 用法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行:

 
  1. [[email protected] ~]# sed '1p' /etc/hosts
  2. 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
  3. 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
  4. ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6

可以發現所有的行都被顯示出來了(第1行重複2次)。—— 正確的用法應該新增 -n 選項,這樣就可以只顯示第1行了:

 
  1. [[email protected] ~]# sed -n '1p' /etc/hosts
  2. 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4

行號可以是連續的行號,如列印passwd第3到第6行賬戶的資訊:

 
  1. [[email protected] ~]# sed -n '3,6p' /etc/passwd
  2. bin:x:1:1:bin:/bin:/sbin/nologin
  3. daemon:x:2:2:daemon:/sbin:/sbin/nologin
  4. adm:x:3:4:adm:/var/adm:/sbin/nologin
  5. lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

2)sed命令的 -i 選項

正常情況下,sed命令所做的處理只是把操作結果(包括列印、刪除等)輸出到當前終端螢幕,而並不會對原始檔案做任何更改:

 
  1. [[email protected] ~]# sed 'd' /etc/passwd                     //刪除所有行
  2. [[email protected] ~]# cat /etc/passwd                         //檢視原始文字,並未改動

若希望直接修改檔案內容,應新增選項 -i 。

比如,直接刪除test.txt(自行建立一個任意內容的檔案)的第1~4行:

 
  1. [[email protected] ~]# sed -i '1,4d' test.txt         //刪除操作
  2. [[email protected] ~]# cat test.txt                     //確認刪除結果

下文中關於使用sed修改檔案的示例中,為了避免大家在練習過程中因誤操作導致系統故障,命令省略 –i 選項,不再逐一說明。需要時,大家可自行加上此選項。

3)多個指令可以使用分號隔離

用分號來隔離多個操作,比如:

 
  1. [[email protected] ~]# sed -n '1p;4p' /etc/passwd
  2. root:x:0:0:root:/root:/bin/bash
  3. adm:x:3:4:adm:/var/adm:/sbin/nologin

步驟二:認識sed工具的條件

# sed [選項] '條件指令' 檔案.. ..

sed命令可以使用行號或正則做為條件匹配:

1)行號案例

列印第3行:

 
  1. [[email protected] ~]# sed -n '3p' /etc/passwd

列印第3到5行:

 
  1. [[email protected] ~]# sed -n '3,5p' /etc/passwd

列印第3和5行:

 
  1. [[email protected] ~]# sed -n '3p;5p' /etc/passwd

列印第3以及後面的10行:

 
  1. [[email protected] ~]# sed -n '3,+10p' /etc/passwd

列印奇數行:

 
  1. [[email protected] ~]# sed -n '1~2p' /etc/passwd

列印偶數行:

 
  1. [[email protected] ~]# sed -n '2~2p' /etc/passwd

2)正則案例

列印包含root的行:

 
  1. [[email protected] ~]# sed -n '/root/p' /etc/passwd

列印bash結尾的行:

 
  1. [[email protected] ~]# sed -n '/bash$/p' /etc/passwd

3)沒有條件,則表示匹配所有行

 
  1. [[email protected] ~]# sed -n 'p' /etc/passwd

步驟三:sed工具的p、d、s操作指令案例集合

1)下面看看sed工具的p指令案例集錦(自己提前生成一個a.txt檔案)

 
  1. [[email protected] ~]# sed -n 'p' a.txt            //輸出所有行,等同於cat a.txt
  2. [[email protected] ~]# sed -n '4p' a.txt            //輸出第4行
  3. [[email protected] ~]# sed -n '4,7p' a.txt        //輸出第4~7行
  4. [[email protected] ~]# sed -n '4,+10p' a.txt        //輸出第4行及其後的10行內容
  5. [[email protected] ~]# sed -n '/^bin/p' a.txt        //輸出以bin開頭的行
  6. [[email protected] ~]# sed -n '$=' a.txt            //輸出檔案的行數

2)下面看看sed工具的d指令案例集錦(自己提前生成一個a.txt檔案)

 
  1. [[email protected] ~]# sed '3,5d' a.txt             //刪除第3~5行
  2. [[email protected] ~]# sed '/xml/d' a.txt            //刪除所有包含xml的行
  3. [[email protected] ~]# sed '/xml/!d' a.txt         //刪除不包含xml的行,!符號表示取反
  4. [[email protected] ~]# sed '/^install/d' a.txt    //刪除以install開頭的行
  5. [[email protected] ~]# sed '$d' a.txt                //刪除檔案的最後一行
  6. [[email protected] ~]# sed '/^$/d' a.txt             //刪除所有空行

3)sed命令的s替換基本功能(s/舊內容/新內容/選項):

 
  1. [[email protected] ~]# vim test.txt             //新建素材
  2. 2017 2011 2018
  3. 2017 2017 2024
  4. 2017 2017 2017
  5.  
  6. [[email protected] ~]# sed 's/2017/xxxx/' test.txt
  7. [[email protected] ~]# sed 's/2017/xxxx/g' test.txt
  8. [[email protected] ~]# sed 's/2017/xxxx/2' test.txt
  9. [[email protected] ~]# sed 's/2017//2' test.txt
  10. [[email protected] ~]# sed -n 's/2017/xxxx/p' test.txt

4)下面看看sed工具的s指令案例集錦(自己提前生成一個a.txt檔案)

注意:替換操作的分隔“/”可改用其他字元,如#、&等,便於修改檔案路徑

 
  1. [[email protected] ~]# sed 's/xml/XML/' a.txt        //將每行中第一個xml替換為XML
  2. [[email protected] ~]# sed 's/xml/XML/3' a.txt     //將每行中的第3個xml替換為XML
  3. [[email protected] ~]# sed 's/xml/XML/g' a.txt     //將所有的xml都替換為XML
  4. [[email protected] ~]# sed 's/xml//g' a.txt     //將所有的xml都刪除(替換為空串)
  5. [[email protected] ~]# sed 's#/bin/bash#/sbin/sh#' a.txt //將/bin/bash替換為/sbin/sh
  6. [[email protected] ~]# sed '4,7s/^/#/' a.txt         //將第4~7行註釋掉(行首加#號)
  7. [[email protected] ~]# sed 's/^#an/an/' a.txt         //解除以#an開頭的行的註釋(去除行首的#號)

步驟四:利用sed完成本例要求的任務

參考資料檔案內容如下:

 
  1. [[email protected] ~]# cat nssw.txt
  2. Hello the world
  3. ni hao ma beijing

本小節的操作使用nssw.txt作為測試檔案。

1)刪除檔案中每行的第二個、最後一個字元

分兩次替換操作,第一次替換掉第2個字元,第二次替換掉最後一個字元:

 
  1. [[email protected] ~]# sed 's/.//2 ; s/.$//' nssw.txt

2)將檔案中每行的第一個、倒數第1個字元互換

每行文字拆分為“第1個字元”、“中間的所有字元”、“倒數第1個字元”三個部分,然後通過替換操作重排順序為“3-2-1”:

 
  1. [[email protected] ~]# sed -r 's/^(.)(.*)(.)$/\3\2\1/' nssw.txt

3)刪除檔案中所有的數字

因原檔案內沒有數字,行首也沒有空格,這裡稍作做一點處理,生成一個新測試檔案:

 
  1. [[email protected] ~]# sed 's/[0-9]//' nssw.txt

以nssw2.txt檔案為例,刪除所有數字、行首空格的操作如下:

 
  1. [[email protected] ~]# sed -r 's/[0-9]//g;s/^( )+//' nssw2.txt

4)為檔案中每個大寫字母新增括號

使用“()”可實現保留功能,所以可參考下列操作解決:

 
  1. [[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)根據實現思路編寫指令碼檔案

 
  1. [[email protected] ~]# vim anonftp.sh
  2. #!/bin/bash
  3. yum -y install vsftpd                             //安裝vsftpd軟體
  4. cp /etc/vsftpd/vsftpd.conf{,.bak}                 //備份預設的配置檔案
  5. sed -i "s/^#anon/anon/" /etc/vsftpd/vsftpd.conf     //修改服務配置
  6. chmod 777 /var/ftp/pub                             //調整目錄許可權
  7. systemctl start vsftpd                             //啟動服務
  8. systemctl enable vsftpd                            //設為自動執行
  9.  
  10. [[email protected] ~]# chmod +x anonftp.sh
  11. [[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檔案,需要自己建立一個測試檔案!!!

 
  1. [[email protected] ~]# sed '2a XX' a.txt            //在第二行後面,追加XX
  2. [[email protected] ~]# sed '2i XX' a.txt            //在第二行前面,插入XX
  3. [[email protected] ~]# sed '2c XX' a.txt            //將第二行替換為XX

實現此案例需要按照如下步驟進行。

步驟一:修改主機名配置檔案

1)確認修改前的配置

 
  1. [[email protected] ~]# cat /etc/hostname
  2. svr5.tarena.com

2)使用sed修改主機名配置所在行的內容(c整行替換)

 
  1. [[email protected] ~]# sed '1c mysvr.tarena.com' /etc/hostname

步驟二:修改hosts檔案,新增新的記錄

1)確認修改前的配置

 
  1. [[email protected] ~]# cat /etc/hosts
  2. 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
  3. ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6

2)使用sed修改hosts檔案,新增兩行新紀錄(a追加)

 
  1. [[email protected] ~]# sed -i '$a 192.168.4.5 svr5.tarena.com svr5' /etc/hosts
  2. 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
  3. ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
  4. 192.168.4.5 svr5.tarena.com svr5

4 案例4:sed綜合指令碼應用

4.1 問題

本案例要求編寫指令碼getupwd.sh,實現以下需求:

  • 找到使用bash作登入Shell的本地使用者
  • 列出這些使用者的shadow密碼記錄
  • 按每行“使用者名稱 --> 密碼記錄”儲存到getupwd.log,如圖-1所示

圖-1

4.2 方案

基本思路如下:

  1. 先用sed工具取出登入Shell為/bin/bash的使用者記錄,儲存為臨時檔案/tmp/urec.tmp,並計算記錄數量
  2. 再結合while迴圈遍歷取得的賬號記錄,逐行進行處理
  3. 針對每一行使用者記錄,採用掐頭去尾的方式獲得使用者名稱、密碼字串
  4. 按照指定格式追加到/tmp/getuupwd.log檔案
  5. 結束迴圈後刪除臨時檔案,報告分析結果

4.3 步驟

實現此案例需要按照如下步驟進行。

步驟一:編寫getupwd.sh指令碼

 
  1. [[email protected] ~]# vim ./getupwd.sh
  2. #/bin/bash
  3. A=$(sed -n '/bash$/s/:.*//p' /etc/passwd)             ## 提取符合條件的賬號記錄
  4. for i in $A                                     ##遍歷賬號記錄
  5. do
  6. pass1=$(grep $i /etc/shadow)
  7. pass2=${pass1#*:}
  8. pass=${pass2%%:*}
  9. echo "$i --> $pass"
  10. done
  11.  
  12. [[email protected] ~]# chmod +x ./getupwd.sh

步驟二:測試、驗證執行結果

 
  1. [[email protected] ~]# ./getupwd.sh
  2. 使用者分析完畢,請查閱檔案 /tmp/getupwd.log
  3.  
  4. [[email protected] ~]# less /tmp/getupwd.log
  5. root --> $6$IWgMYmRACwdbfwBo$dr8Yn983nswiJVw0dTMjzbDvSLeCd1GMYjbvsDiFEkL8jnXOLcocBQypOCr4C6BRxNowIxjh6U2qeFU0u1LST/
  6. zengye --> $6$Qb37LOdzRl5995PI$L0zTOgnhGz8ihWkW81J.5XhPp/l7x2./Me2ag0S8tRndCBL9nIjHIKkUKulHxJ6TXyHYmffbVgUT6pbSwf8O71
  7. clamav --> !!
  8. mysql --> !!
  9. abc --> !!
  10. .. ..

從上述參考指令碼可以發現,使用sed來實現欄位提取會比較複雜。下一章課程將會學到awk命令,屆時可以通過更簡單的方法來改進此指令碼內容。

總結知識點:

#sed [選項] '條件指令' 檔案

選項:

-n 遮蔽預設輸出

-r 支援擴充套件正則

-i 修改原始檔

條件:

行號 4 4,5 4~2 4,+10

/正則/

指令:

p 列印

d 刪除

s 替換s/舊/新/g

a 追加

i 插入

c 替換行