Linux sed
Stream EDitor,流式編輯器
- 非交互,基於模式匹配過慮及修改文件
- 逐行處理,並將結果輸出到屏幕
- 可實例對文本的輸出、刪除、替換、複製、剪切、導入、導出等各種操作
一、基本正則列表與擴展正則
根據推出時間的不同,分為基本正則和擴展正則,擴展正則在基本正則的基礎上做了一些優化和新增了一些正則表達符號,因為一些命令沒有及時更新,所以你可能會遇到有些命令只支持基本正則,不支持擴展正則,或者需要添加一些支持擴展正則的選項。
關於正則與擴展正則區別的詳細介紹可以看我另一篇shell 正則的介紹
基本正則列表
擴展正則列表
二、sed 文本處理工具的用法介紹:
- 用法1:前置命令 | sed [選項]'條件指令'
- 用法2:sed [選項]'條件指令' 文件....
相關説明如下:
- 條件可以是行號或者/正則/
- 沒有條件時,默認為所有條件
- 指令可以是增、刪、改、查等指令
- 默認sed會將所有輸出的內容都打印出來,可以使用-n屏蔽默認輸出
- 選項中可以使用-r選項,讓sed支持擴展正則
sed命令的常用選項如下:
- -n 屏蔽默認輸出,默認sed會輸出讀取文檔的全部內容
- -r 讓sed支持擴展正則 若與其它選項一起使用,應放作為首選項
- -i sed直接修改源文件,默認sed只是通過內存臨時修改文件,源文件無影響
- -e 多點編輯 讓一條sed可以執行多條指令
sed命令常用條件指令如下
- d:刪除指定的字符
- p:顯示指定的行
- s:替換指定的字符
- i: 在指定的行之前插入文本
- a:在指定的行之後追加文本
- c:替換指定的行
- r:讀取文件
- w:保存到文件
三、認識sed工具的 n、r、i 選項指令
\# sed [選項] '條件指令' 文件.. ..
上面的條件指令 我們可以拆分為 # sed [選項] '範圍界定+操作指令' 文件.. .. 的格式這樣更容易理解
sed -n '/bash$/ s/:.*//p' /etc/passwd // 選項 -n 範圍界定/bash$/ + 操作指令s/:.*//p
sed命令可以使用行號或正則做為條件匹配:
1)sed命令的 -n 選項
執行p打印等過濾操作時,希望看到的是符合條件的文本。但不使用任何選項時,默認會將原始文本一併輸出,從而干擾過濾效果。比如,嘗試用sed輸出/etc/hosts的第1行:
[root@server ~]# 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行了:
[root@server ~]# sed -n '1p'/etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
行號可以是連續的行號,如打印passwd第3到第6行賬户的信息:
[root@server ~]# 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命令的 -r 選項
需要用到擴展正則時,需要加 -r選項
[root@server ~]# sed -r 's/bash|nologin/xxxx/g' '/etc/passwd //把所有bash或nologin替換為xxxx
3)sed命令的 -i 選項
正常情況下,sed命令所做的處理只是把操作結果(包括打印、刪除等)輸出到當前終端屏幕,而並不會對原始文件做任何更改:
[root@server ~]# sed 'd'/etc/passwd //刪除所有行
[root@server ~]# cat /etc/passwd //查看原始文本,並未改動
若希望直接修改文件內容,應添加選項 -i 。
需要特別注意的是,和一些指令組合和使用的先後順序都會對最終輸出結果產生影響
例如: 指令 -n、和操作操作p
[root@server ~]# sed -in 's/2017/xxx/' test.txt // n在i後面不影響結果
[root@server ~]# cat test.txt
xxx20112018
xxx20172024
xxx20172017
[root@server ~]# sed -ni 's/2017/xxx/' test.txt // n在i前面 因為n已經屏蔽了所有顯示 所以結果為空
[root@server ~]# cat test.txt
[root@server ~r]# sed -in 's/2018$/xxx/p' test.txt // n在i後面不影響結果 但P後面的顯示指令 讓匹配項重複顯示行寫入到了文件
[root@server ~]# cat test.txt
20172011xxx
20172011xxx
201720172024
201720172017
[root@server ~]# sed -ni 's/2018$/xxx/p' test.txt # n在i前面 後面 P指令只把匹配項寫入了文件
[root@server ~]# cat test.txt
20172011xxx
比如,直接刪除test.txt(自行創建一個任意內容的文件)的第1~4行:
[root@server ~]# sed -i '1,4d' test.txt //刪除操作
[root@server ~]# cat test.txt //確認刪除結果
下文中關於使用sed修改文件的示例中,為了避免大家在練習過程中因誤操作導致系統故障,命令省略 –i 選項,不再逐一説明。需要時,大家可自行加上此選項。
4)多個指令可以使用分號隔離
用分號來隔離多個操作,比如:
[root@server ~]# sed -n '1p;4p'/etc/passwd
root:x:0:0:root:/root:/bin/bash
adm:x:3:4:adm:/var/adm:/sbin/nologin
1)行號案例
打印第3行:
[root@server ~]# sed -n '3p'/etc/passwd
打印第3到5行:
[root@server ~]# sed -n '3,5p'/etc/passwd
打印第3和5行:
[root@server ~]# sed -n '3p;5p'/etc/passwd
打印第3以及後面的10行:
[root@server ~]# sed -n '3,+10p'/etc/passwd
打印奇數行:
[root@server ~]# sed -n '1~2p'/etc/passwd
打印偶數行:
[root@server ~]# sed -n '2~2p'/etc/passwd
2)正則案例
打印包含root的行:
[root@server ~]# sed -n '/root/p'/etc/passwd
打印bash結尾的行:
[root@server ~]# sed -n '/bash$/p'/etc/passwd
3)沒有條件,則表示匹配所有行
[root@server ~]# sed -n 'p'/etc/passwd
四、認識sed工具的 p、d、s 條件指令
1)下面看看sed工具的p指令案例集錦(自己提前生成一個a.txt文件)
[root@server ~]# sed -n 'p' a.txt //輸出所有行,等同於cat a.txt
[root@server ~]# sed -n '4p' a.txt //輸出第4行
[root@server ~]# sed -n '4,7p' a.txt //輸出第4~7行
[root@server ~]# sed -n '4,+10p' a.txt //輸出第4行及其後的10行內容
[root@server ~]# sed -n '/^bin/p' a.txt //輸出以bin開頭的行
[root@server ~]# sed -n '$=' a.txt //輸出文件的行數
2)下面看看sed工具的d指令案例集錦(自己提前生成一個a.txt文件)
[root@server ~]# sed '3,5d' a.txt //刪除第3~5行
[root@server ~]# sed '/xml/d' a.txt //刪除所有包含xml的行
[root@server ~]# sed '/xml/!d' a.txt //刪除不包含xml的行,**!符號表示取反**
[root@server ~]# sed '/^install/d' a.txt //刪除以install開頭的行
[root@server ~]# sed '$d' a.txt //刪除文件的最後一行
[root@server ~]# sed '/^$/d' a.txt //刪除所有空行
3)sed命令的s替換基本功能(s/舊內容/新內容/選項):
[root@svr5 ~]# vim test.txt //新建素材
201720112018
201720172024
201720172017
[root@server ~]# sed 's/2017/xxxx/' test.txt //將每行中第一個2017替換為xxxx
[root@server ~]# sed 's/2017/xxxx/g' test.txt //將每行中所有2017替換為xxxx
[root@server ~]# sed 's/2017/xxxx/2' test.txt //將每行中第2個2017替換為xxxx
[root@server ~]# sed 's/2017//2' test.txt //將每行中第2個2017刪除
[root@server ~]# sed -n 's/2017/xxxx/p' test.txt //將每行中第一個2017替換為xxxx 並顯示
4)下面看看sed工具的s指令案例集錦(自己提前生成一個a.txt文件)
注意:替換操作的分隔“/”可改用其他字符,如#、&等,便於修改文件路徑
[root@server ~]# sed 's/xml/XML/' a.txt //將每行中第一個xml替換為XML
[root@server ~]# sed 's/xml/XML/3' a.txt //將每行中的第3個xml替換為XML
[root@server ~]# sed 's/xml/XML/g' a.txt //將所有的xml都替換為XML
[root@server ~]# sed 's/xml//g' a.txt //將所有的xml都刪除(替換為空串)
[root@server ~]# sed 's#/bin/bash#/sbin/sh#' a.txt //將/bin/bash替換為/sbin/sh
[root@server ~]# sed '4,7s/^/#/' a.txt //將第4~7行註釋掉(行首加#號)
[root@server ~]# sed 's/^#an/an/' a.txt //解除以#an開頭的行的註釋(去除行首的#號)
以下操作使用nssw.txt作為測試文件。
參考數據文件內容如下:
[root@server ~]# cat nssw.txt
Hello the world
ni hao ma beijing
5)刪除文件中每行的第二個、最後一個字符
分兩次替換操作,第一次替換掉第2個字符,第二次替換掉最後一個字符:
[root@server ~]# sed 's/.//2 ; s/.$//' nssw.txt
6)將文件中每行的第一個、倒數第1個字符互換
每行文本拆分為“第1個字符”、“中間的所有字符”、“倒數第1個字符”三個部分,然後通過替換操作重排順序為“3-2-1”:
[root@server~]# sed -r 's/^(.)(.*)(.)$/\3\2\1/' nssw.txt
7)刪除文件中所有的數字
因原文件內沒有數字,行首也沒有空格,這裏在內容中新增一些數字另外新幾行內容 首行添加幾行空格,生成一個新測試文件以 nssw2.txt
[root@server ~]# sed 's/[0-9]//' nssw.txt //無效因為裏面不包含數字
以nssw2.txt文件為例,刪除所有數字、行首空格的操作如下:
[root@server ~]# sed -r 's/[0-9]//g;s/^( )+//' nssw2.txt
8)為文件中每個大寫字母添加括號[]
使用“()”可實現保留功能,所以可參考下列操作解決:
[root@server ~]# sed -r 's/([A-Z])/[\1]/g' nssw.txt
五、認識sed工具的 i、a、c 條件指令
\# sed [選項] '條件指令' 文件..
sed工具的多行文本處理操作:
- i: 在指定的行之前插入文本
- a:在指定的行之後追加文本
- c:替換指定的行
基本語法格式案例:
[root@server ~]# sed '2a XX' a.txt //在第二行後面,追加XX
[root@server ~]# sed '2i XX' a.txt //在第二行前面,插入XX
[root@server ~]# sed '2c XX' a.txt //將第二行替換為XX
1)sed命令的 i 指定行之前插入基本功能
[root@server ~]# sed '2i xxxx' nssw.txt //將第二行前插入xxxx
[root@server ~]# sed 'c xxxx' nssw.txt //在所有行前插入xxxx
2)sed命令的a追加基本功能
[root@server ~]# sed '3a xxxx' nssw.txt //將第三行後追加xxxx
[root@server ~]# sed 'a xxxx' nssw.txt //在所有行後追加xxxx
3)sed命令的c替換基本功能
[root@server ~]# sed '1c xxxx' nssw.txt //將第一行替換為xxxx
[root@server ~]# sed 'c xxxx' nssw.txt //對所有行替換成xxx
[root@server ~]# sed '1,3c xxxx' nssw.txt //對1到3行替換成xxx
六、認識sed高級應用 r、w 條件指令
新建文件 a.txt n.txt
[root@server sed]# cat a.txt
aabbccdd
eeffgghh
iijjkkll
[root@server sed]# cat n.txt
11223344
55667788
99001122
1)sed命令的 r 讀取文件
[root@server sed]# sed '2r a.txt' n.txt \\在第2行插入a.txt
11223344
55667788
aabbccdd
eeffgghh
iijjkkll
99001122
[root@server sed]# sed '/^ee/r n.txt' a.txt \\在以ee開頭的行下方插入n.txt
aabbccdd
eeffgghh
11223344
55667788
99001122
iijjkkll
[root@server sed]# sed '1,3r n.txt' a.txt \\在以1到3行下方分別插入n.txt
2)sed命令的 w 保存到文件
[root@server sed]# sed -n '1,3w c.txt' a.txt \\把1到3主存儲為新文件c.txt
[root@server sed]# cat c.txt
aabbccdd
eeffgghh
iijjkkll
[root@server sed]# sed -n '/^ii/w d.txt' a.txt \\把ii開頭的行保存為d.txt
[root@server sed]# cat d.txt
iijjkkll
七、綜合案例
1) 綜合案例1
[root@server sed]# cp /etc/passwd .
[root@server sed]# nl /etc/passwd | sed '2,5d' // **刪除2到5行 | 管道後使用 -i 選項無效**
[root@server sed]# nl passwd | sed '3,$d' //刪除3到最後一行
[root@server sed]# nl passwd | sed '2i hostfile' > passwd.new //在第2行前插入''hostfile'' 並生成新文件 passwd.new
[root@server sed]# nl passwd | sed -n '/root/p' //顯示包含root的行
[root@server sed]# nl /etc/passwd | sed '/root/{s/bash/black/;p;q}' //花括號中的一組命令,每個命令之間用分號分隔,找到root的行把bash替換成clack p輸出顯示 q是退出
[root@server sed]# ifconfig eth0 | grep 'inet'|sed 's/inet\s//g'|sed 's/\snetmask.*$//g' \\獲取本機的IP地址 其中\s 表示匹配空格
[root@server sed]# sed -e '3,$d' -e 's/bash/blueshell/' passwd // 多點編輯 一條sed命令,刪除/etc/passwd第三行到末尾的數據,並把bash替換為blueshell
root:x:0:0:root:/root:/bin/blueshell
bin:x:1:1:bin:/bin:/sbin/nologin
2)綜合案例2 腳本應用
- 本案例要求編寫腳本getupwd.sh,實現以下需求:
找到使用bash作登錄Shell的本地用户
列出這些用户的shadow密碼記錄
按每行“用户名 --> 密碼記錄”保存到getupwd.log - 基本思路如下:
先用sed工具取出登錄Shell為/bin/bash的用户記錄,保存為臨時文件/tmp/urec.tmp,並計算記錄數量
再結合while循環遍歷取得的賬號記錄,逐行進行處理
針對每一行用户記錄,採用掐頭去尾的方式獲得用户名、密碼字串
按照指定格式追加到/tmp/getuupwd.log文件
結束循環後刪除臨時文件,報告分析結果 -
腳本的編寫
步驟一:編寫getupwd.sh腳本[root@server sed]# cat getupwd.sh #!/bin/bash A=$(sed -n '/bash$/ s/:.*//p' /etc/passwd) ##提取符合條件的帳號記錄 for i in $A ##遍歷帳號記錄 do pass1=$(grep $i /etc/shadow) ##搜索對應帳號shadow中的行 pass2=${pass1#*:} pass=${pass2%%:*} ##截取密碼 echo "$i -->$pass" done [root@server sed]# ./getupwd.sh root -->$6$SAyc777Q$DgGi7Pnln0or.Ds04oyL6Y.QnVlMgZDRHMKKICJhiUAHBy4lvziPAZoW0MJz81xYonskLozvzhvNa4H59ngSl1 nginx -->!! bigyong -->!! kaka5 -->$6$uyZDpbUl$.CjkBefPZHXrRTcKc1csv7ZbbhHMMD4oQmum9lajJ1ot9at6fmIey5AE4kmUSoaWE/ofmFxyP2Dc6PAcczXdw0 harry -->!!