###################################################
shell 腳本編程
一、sed基本用法
1.sed命令解析
1)sed工具概述
stream editor 流式編輯器
--非交互,腳本里用sed,命令行用vim。(vim交互式,進出都需對應模式)
--逐行處理,並將結果輸出到屏幕。每次只讀一行,大文本處理快。
########################################
clone-vm7 克隆虛擬機
read -p “Enter number:” num
1. 快速建立前端盤:qemu-img create -f qcow2 -b /var/lib/libvirt/images//rhel7.qcow2 /var/lib/libvirt/images/rhel7 -$num.qcow2
2. 復制配置文件: cp ../images/rhel7.xml ../images/rhel7-$num.xml
3. 修改配置文件: <name,UUID,source,MAC,disk> --> sed ../images/rhel7-$num.xml
4. 定義新虛擬機: virsh define ../images/rhel7-$num.xml
########################################
2)sed文本處理工具的用法格式:
用法1: sed [選項] '條件指令' 文件
用法2: 前置命令 | sed [選項] '條件指令'
定址符
########################################
條件:行號、/正則/ 指令:增刪改查
選項:-n 屏蔽默認全部的輸出 (sed 默認會把整個文件輸出)
-i 直接修改文件內容(sed默認不改源文件,把修改后的結果輸出到屏幕上,腳本要上加i)
-r 啟用擴展正則(默認不啟用),若與其他選項一起使用,應作為首個選項
-{}:可組合多個命令,以分號分隔
#sed -n '3p' /etc/hosts /只輸出第3行
sed -n '/正則/p' 文件
#sed -n '/[0-9]/p' /etc/hosts
########################################
指令:
sed ‘3d;11d;55d’ /etc/hosts
d 刪除行 'd ' 沒條件則匹配所有,全部刪除; '3d' 刪除第三行
p 打印行/輸出行 #sed '3p' /etc/hosts /多了第三行的復制版
s 修改 字符串替換 s/老/新/3 第三個老的,g為所有
替換操作的分隔( /) 可改用其他字符,如#、&等,便於修改文件路徑
########################################
1)刪除文件中每行的第二個、最后一個字符
分兩次替換操作,第一次替換掉第2個字符,第二次替換掉最后一個字符:
[root@svr5 ~]# sed 's/.//2;s/.$//' nssw.txt
2)將文件中每行的第一個、第二個字符互換
每行文本拆分為“第1個字符”、“第2個字符”、“剩下的所有字符”三個部分,然后通過替換操作重排順序為“2-1-3”:
[root@svr5 ~]# sed -r 's/^(.)(.)(.*)/\2\1\3/' nssw.txt
3)刪除文件中所有的數字、行首的空格
因原文件內沒有數字,行首也沒有空格,這里稍作做一點處理,生成一個新測試文件:
[root@svr5 ~]# sed 's/o/o7/;s/l/l4/;3,5s/^/ /' nssw.txt > nssw2.txt
以nssw2.txt文件為例,刪除所有數字、行首空格的操作如下:
[root@svr5 ~]# sed -r 's/[0-9]//g;s/^( )+//' nssw2.txt
4)為文件中每個大寫字母添加括號
使用“&”可調用s替換操作中的整個查找串,所以可參考下列操作解決:
[root@svr5 ~]# sed 's/[A-Z]/(&)/g' nssw.txt
########################################
2)修改IP地址的網段部分,主機地址不變。
直接修改網卡eth0的配置文件,檢查原有的配置內容:
[root@svr5 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
IPADDR=192.168.4.4
TYPE=Ethernet
若希望將IP地址192.168.4.4修改為172.16.16.4,則應該定位到“IPADDR”所在的行,執行相應的替換(僅測試,尚未修改):
[root@svr5 ~]# sed '/^IPADDR/s/192.168.4.4/172.16.16.4/' /etc/sysconfig/network-scripts/ifcfg-eth0 | grep "^IPADDR"
PADDR=172.16.16.4
要求只修改網段地址時,可以利用擴展正則表達式的 \1、\2、……等調用,分別對應此前第1個、第2個、…… 以 ()包圍的表達式所匹配的內容。
所以上述操作可以改為如下(啟用擴展匹配應添加 -r 選項):
[root@svr5 ~]# sed -r -i '/^IPADDR/s/192.168.4.(.*)/172.16.16.\1/'
/etc/sysconfig/network-scripts/ifcfg-eth0
確認修改結果:
[root@svr5 ~]# grep "^IPADDR" /etc/sysconfig/network-scripts/ifcfg-eth0
IPADDR=172.16.16.4
再改回去:
[root@svr5 ~]# sed -r -i '/^IPADDR/s/172.16.16.(.*)/192.168.4.\1/'
/etc/sysconfig/network-scripts/ifcfg-eth0
[root@svr5 ~]# grep "^IPADDR" /etc/sysconfig/network-scripts/ifcfg-eth0
IPADDR=192.168.4.4
3)調整httpd服務配置,更改網站根目錄
由於需要替換的字符串中有 / ,為了避免與sed替換操作的分隔混淆,可以使用其他字符作為替換分隔,比如可改用“s#old#new#”的方式實現替換:
[root@svr5 ~]# sed -i 's#/var/www/html#/opt/wwwroot#'
/etc/httpd/conf/httpd.conf
[root@svr5 ~]# grep "^DocumentRoot" /etc/httpd/conf/httpd.conf
DocumentRoot "/opt/wwwroot"
若要恢復,可再改回去:
[root@svr5 ~]# sed -i 's#/opt/wwwroot#/var/www/html#'
/etc/httpd/conf/httpd.conf
[root@svr5 ~]# grep "^DocumentRoot" /etc/httpd/conf/httpd.conf
DocumentRoot "/var/www/html"
########################################
通過yum安裝vsftpd軟件包
- 修改vsftpd服務配置,開啟匿名上傳
- 調整/var/ftp/pub目錄權限,允許ftp寫入
- 啟動vsftpd服務,並設置開機自運行
步驟二:編寫anonftp.sh腳本,用來裝配匿名FTP服務
1)任務需求及思路分析
vsftpd服務的安裝、改目錄權限、起服務等操作可以直接寫在腳本中。
修改vsftpd.conf配置的工作可以使用sed命令,根據默認配置,只需要定位到以#anon開頭的行,去掉開頭的注釋即可。
2)根據實現思路編寫腳本文件
[root@svr5 ~]# vim anonftp.sh
#!/bin/bash
yum -y install vsftpd //安裝vsftpd軟件
cp /etc/vsftpd/vsftpd.conf{,.bak} //備份默認的配置文件
sed -i "/^#anon/s/^#//" /etc/vsftpd/vsftpd.conf //修改服務配置
chown ftp /var/ftp/pub //調整目錄權限
/etc/init.d/vsftpd restart //啟動服務
chkconfig vsftpd on //設為自動運行
[root@svr5 ~]# chmod +x anonftp.sh
3)驗證、測試腳本
運行腳本anonftp.sh:
[root@svr5 ~]# ./anonftp.sh
Complete!關閉 vsftpd: [失敗]
為 vsftpd 啟動 vsftpd: [確定]
使用ftp登錄服務,測試是否可以上傳:
[root@svr5 ~]# ftp localhost //本機訪問測試
Connected to localhost.localdomain.220 (vsFTPd 2.0.5)530 Please login with USER and PASS.530 Please login with USER and PASS.KERBEROS_V4 rejected as an authentication
typeName (localhost:root): ftp //匿名登錄331
Please specify the password.Password:230 Login successful.Remote system type is UNIX.Using binary mode to transfer
files.ftp> cd pub //切換到 pub/ 目錄250
Directory successfully changed.ftp> put install.log //上傳當前目錄下的
install.log 文件local: install.log remote: install.log227 Entering Passive Mode (127,0,0,1,192,127)150 Ok to send data.226 File receive OK.33139 bytes sent in 0.0065 seconds (5e+03 Kbytes/s)
ftp> quit //斷開FTP連接221 Goodbye.
查看/var/ftp/pub新上傳的文件:
[root@svr5 ~]# ls -lh /var/ftp/pub/總計 36K-rw------- 1 ftp ftp 33K 12-13 18:25 install.log
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工具的多行文本處理操作:
- i:在指定的行之前插入文本
- a:在指定的行之后追加文本
- c:替換指定的行
3.3 步驟
實現此案例需要按照如下步驟進行。
步驟一:修改主機名配置文件
1)確認修改前的配置
[root@svr5 ~]# cat /etc/sysconfig/network
NETWORKING=yes HOSTNAME=svr5.tarena.com
2)使用sed修改主機名配置所在行的內容(c整行替換)
[root@svr5 ~]# sed '/^HOSTNAME/cHOSTNAME=mysvr.tarena.com' /etc/sysconfig/network
步驟二:修改hosts文件,添加新的記錄
1)確認修改前的配置
[root@svr5 ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4::1
localhost localhost.localdomain localhost6 localhost6.localdomain6
2)使用sed修改hosts文件,添加兩行新紀錄(a追加)
[root@svr5 ~]# sed -i '$a192.168.4.5 svr5.tarena.com svr5\> 119.75.217.56 www.baidu.com' /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4::1
localhost localhost.localdomain localhost6 localhost6.localdomain6192.168.4.5 svr5.tarena.com svr5119.75.217.56 www.baidu.com
4 案例4:sed綜合腳本應用
4.1 問題
本案例要求編寫腳本getupwd.sh,實現以下需求:
- 找到使用bash作登錄Shell的本地用戶
- 列出這些用戶的shadow密碼記錄
- 按每行“用戶名 --> 密碼記錄”保存到getupwd.log,如圖-1所示
4.2 方案
基本思路如下:
- 先用sed工具取出登錄Shell為/bin/bash的用戶記錄,保存為臨時文件/tmp/urec.tmp,並計算記錄數量
- 再結合while循環遍歷取得的賬號記錄,逐行進行處理
- 針對每一行用戶記錄,采用掐頭去尾的方式獲得用戶名、密碼字串
- 按照指定格式追加到/tmp/getuupwd.log文件
- 結束循環后刪除臨時文件,報告分析結果
4.3 步驟
實現此案例需要按照如下步驟進行。
步驟一:編寫getupwd.sh腳本
[root@svr5 ~]# vim ./getupwd.sh
#/bin/bash
> /tmp/getupwd.log ## 創建空文件
sed -n '/:\/bin\/bash$/w /tmp/urec.tmp' /etc/passwd ## 提取符合條件的賬號記錄
UNUM=$(egrep -c '.' /tmp/urec.tmp) ## 取得記錄個數
while [ ${i:=1} -le $UNUM ] ## 從第1行開始,遍歷賬號記錄
do UREC=$(sed -n "${i}p" /tmp/urec.tmp) ## 取指定行數的記錄
NAME=${UREC%%:*} ## 截取用戶名(記錄去尾)
PREC=$(sed -n "/^$NAME:/p" /etc/shadow) ## 查找與用戶名對應的密碼記錄
PASS=${PREC#*:} ## 掐頭
PASS=${PASS%%:*} ## 去尾,只留下密碼記錄
echo "$NAME --> $PASS" >> /tmp/getupwd.log ## 保存結果
let i++ ## 自增1,轉下一次循環
done
/bin/rm -rf /tmp/urec.tmp ## 刪除臨時文件
echo "用戶分析完畢,請查閱文件 /tmp/getupwd.log" ## 完成后提示
[root@svr5 ~]# chmod +x ./getupwd.sh
步驟二:測試、驗證執行結果
[root@svr5 ~]# ./getupwd.sh 用戶分析完畢,請查閱文件 /tmp/getupwd.log
[root@svr5 ~]# less /tmp/getupwd.log root -->
$6$IWgMYmRACwdbfwBo$dr8Yn983nswiJVw0dTMjzbDvSLeCd1GMYjbvsDiFEkL8jnXOLcocBQypOCr4C6BRxNowIxjh6U2qeFU0u1LST/zengye -->
$6$Qb37LOdzRl5995PI$L0zTOgnhGz8ihWkW81J.5XhPp/l7x2./Me2ag0S8tRndCBL9nIjHIKkUKulHxJ6TXyHYmffbVg
UT6pbSwf8O71clamav --> !!mysql --> !!abc --> !!
yinshixiong
正則表達式
^ 開始
$ 結尾
[ ] 集合之一
[0-9]==[0123456789]
[a-f4-7]==[abcdef4567]
[a-Z]==[a-zA-Z]
[^abc]除了abc
. 代表任意單個符號 每次只能代表一個
..
...
.* 代表匹配任意所有
2\{2,5\} 2\{2,\}
a\{3\}
cat abcdefgskaldkjfkla;jd
sed /IPADDR/s
sed 's//172.16.0.\2/' a.txt
([0-9]{1-3}.){3}([0-9]{1})
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
sed -a
[root@17:04:35 /opt/shell05 397]#sed '2a XXX' a.txt
hello the world
the time always go
XXX
filesystem the
[root@17:04:52 /opt/shell05 398]#sed '2i XXX' a.txt
hello the world
XXX
the time always go
filesystem the
[root@17:05:02 /opt/shell05 399]#
sed '/root/s/xxx/xxx1/g' 先進入到有/root/這一行然后再進行其他操作
********************************sed '/root/a xxx ' /etc/passwd 可以是路徑或者其他關鍵詞*******************************
###########################################################################################################################
ab
abb
abbb
ac
ttt
#grep "ab*" txt
ab
abb
abbb
ac
########################
[root@09:54:05 /opt/shell05 55]#grep 't[ea]ste\{0,1\}' regular_express.txt
I can't finish the test.
Oh! The soup taste good.
[root@09:54:17 /opt/shell
[root@09:54:44 /opt/shell05 58]#grep t[ea]ste* regular_express.txt //這個如果有 多個e那么會造成誤判
擴展正則:簡化基本正則
\{2.3\} ==> {n,m}
(|) 或者
添加新的符號
######################################################################################
?
+
teate? 可能有也可能沒有,e可以為0
[root@19:24:45 /opt/shell05 514]#egrep 't[ea]ste?' regular_express.txt
I can't finish the test.
Oh! The soup taste good.
[root@19:24:49 /opt/shell05 515]#egrep 't[ea]ste+' regular_express.txt
Oh! The soup taste good.
teaste+ 最少匹配一次 至少一次e不能沒有
#############################################################################
\b 代表單詞邊界
#用egrep 搜索不要以the開頭的
[root@19:19:15 /opt/shell05 500]#egrep '\b the\b' a.txt
hello the world
filesystem the
##############################################################################
基本正則:兼容性強支持的軟件多,麻煩
擴展:簡單,兼容性差
egrep "(test|taste)" regular_express.txt
I can't finish the test.
Oh! The soup taste good.
##############################################
sed 命令語法格式
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~諸行處理~~~~~~~~~~~~~~
##################################################################################################
sed 【選項】 ‘條件指令’ 文件
sed 'd' 文件 清空文件
sed '3d' 文件 刪除文件第三行
sed '1p' /etc/hosts 默認的情況下,sed /etc/passwd 不加p,會打印一遍文件,如果加上1p那么會再打一遍第一行,所以會出現兩個第一行如下例子
sed '/^#/d' regular_express.txt //可以用^#這個直接搜索到一個字符串開始來刪除!!!
[root@11:45:32 /opt/shell05 156]#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
172.25.0.11 server0 server server0.example.com webapp0.example.com www0.example.com
172.25.0.10 desktop0 desktop desktop0.example.com smtp0.example.com
172.25.254.254 classroom content classroom.example.com content.example.com
172.25.254.250 foundation0 foundation0.example.com rhgls.domain254.example.com
[root@11:45:38 /opt/shell05 157]#
################################################################################################################################################
准確的去查找配置文件中信息:
http.conf
sed -n '/正則/p' 文件
sed -n '/html/p' 文件
[root@11:49:47 /opt/shell05 158]#sed -n '/html/p' /etc/httpd/conf/httpd.conf
# <URL:http://httpd.apache.org/docs/2.4/mod/directives.html>
DocumentRoot "/var/www/html"
<Directory "/var/www/html">
# http://httpd.apache.org/docs/2.4/mod/core.html#options
DirectoryIndex index.html
# To parse .shtml files for server-side includes (SSI):
AddType text/html .shtml
AddOutputFilter INCLUDES .shtml
#ErrorDocument 404 /missing.html
#ErrorDocument 402 http://www.example.com/subscription_info.html
#################################################################################################################################################
sed -i 直接修改文件
sed 不加i 再屏幕上顯示修改的文件
sed 修改 默認都不改源文件
sed -i '3d;2d;1d'
sed -d
sed -p
sed s/替換/g
sed s/old/new/ 單個替換,每行替換第一個,每行只替換一個
sed s/old/new/3 替換每行第幾個個
sed s/old//g 替換所有
擴展替換第一個字符*** -r ***變成擴展
[root@20:15:50 /opt/shell05 724]#sed -r 's#^(.)(.*)(.)$#3\2\1#g' aa.txt
3ello the worlh
3i hao mn
[root@20:16:07 /opt/shell05 725]#sed -r 's#^(.)(.*)(.)$#\3\2\1#g' aa.txt
dello the worlh
ai hao mn
[root@20:16:14 /opt/shell05 726]#
把第二個字符和最后第二個字符對換
sed -r 's#^(.)(.)(.*)(.)(.$)#14325#g'
dello the worlh
ai hao mn
[root@15:56:36 /opt/shell05 379]#
############################
sed '/bash$/d' passwd
替換為空,刪除文章內某個字符或者word
[root@14:31:00 /opt/shell05 317]#sed 's/2000//g' b.txt
2120 2022
2111 2223
2255 2256 2277
2219 2500
2220
2.
sed 's/\/bin\/bash/\sbin\/NB/g' /etc/passwd
3.sed 替換指令中的替換符號‘/’,可以改為任意其他字符,可以為#可以為!也可以為其他任何!
sed 's#/bin/bash#/sbin/NB#g' b.txt
sed 's#/bin/bash#/sbin/NB#g' passwd
sed 's/\/bin/\/bash/\/sbin\/Nologin/'
sed 'sa\abc\a\aa\a\acc\aa' 文件 替換主要是查看沒有被轉義字符轉義的
1 1 1
########################################################################################################################
sed -n '4,+10p' passwd 打印第四行和第四行后面的10行
sed -n '/^bin/p' 以bin開頭的行打印
sed -n 'p;n' 奇數行
sed -n 'n;p' 偶數行
#########################################################################################################################
sed '3,5d' a.txt
sed '/xml/d' a.txt
sed '/xml/d'
sed -n '$=' /etc/passwd
cat /etc/passwd | wc -l
#################################################################
-r sed 'r /etc/hosts a.txt
w sed 'w xx.txt' a.txt
sed '2w xxl.txt' a.txt
[root@svr7 ~]# sed -r 's#=.*\(.*)#=172.16.0.\1#g' /etc/sysconfig/network-scripts/ifcfg-eth0
sed:-e 表達式 #1,字符 25:不匹配的 ) 或 \)
問題:
~~~~~~~~~~~~~~~~~~~~[root@11:30:04 /opt/shell05 144]#ifconfig | egrep 'inet \b' | egrep [0-9]
inet 172.40.55.206 netmask 255.255.255.0 broadcast 172.40.55.255
inet 127.0.0.1 netmask 255.0.0.0
inet 192.168.4.254 netmask 255.255.255.0 broadcast 192.168.4.255
inet 192.168.2.254 netmask 255.255.255.0 broadcast 192.168.2.255
inet 201.1.1.254 netmask 255.255.255.0 broadcast 201.1.1.255
inet 201.1.2.254 netmask 255.255.255.0 broadcast 201.1.2.255
inet 172.25.254.250 netmask 255.255.255.0 broadcast 172.25.254.255
inet 172.25.0.250 netmask 255.255.0.0 broadcast 172.25.255.255
inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
NSD SHELL DAY05
1 案例1:sed基本用法
1.1 問題
本案例要求熟悉sed命令的p、d、s等常見操作,並結合正則表達式,完成以下任務:
刪除文件中每行的第二個、最后一個字符
將文件中每行的第一個、第二個字符互換
刪除文件中所有的數字、行首的空格
為文件中每個大寫字母添加括號
1.2 方案
sed文本處理工具的用法:
用法1:前置命令 | sed [選項] '編輯指令'
用法2:sed [選項] '編輯指令' 文件.. ..
相關說明如下:
“編輯指令”可以為增刪改查等指令
“定址符”用來定義需要操作的文本,由“[地址1 [,地址2]]組成
未指定“定址符”時,默認處理所有文本
1.3 步驟
實現此案例需要按照如下步驟進行。
步驟一:認識sed工具的基本選項
1)sed命令的 -n 選項
執行p打印等過濾操作時,希望看到的是符合條件的文本。但不使用任何選項時,默認會將原始文本一並輸出,從而干擾過濾效果。比如,嘗試用sed輸出/etc/rc.local的第1行:
[root@svr5 ~]# sed '1p' /etc/rc.local
#!/bin/sh
#!/bin/sh
#
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.
可以發現所有的行都被顯示出來了。—— 正確的用法應該添加 -n 選項,這樣就可以只顯示第1行了:
[root@svr5 ~]# sed -n '1p' /etc/rc.local
#!/bin/s
而在執行d刪除等過濾操作時,希望看到的是刪除符合條件的文本之后還能夠被保留下來的文本,所以這時候就不應該使用 -n 選項了。比如,刪除/etc/rc.local文件的第1-4行文本:
[root@svr5 ~]# sed '1,4d' /etc/rc.local
# want to do the full Sys V style init stuff.
touch /var/lock/subsys/local
2)sed命令的 -i 選項
正常情況下,sed命令所做的處理只是把操作結果(包括打印、刪除等)輸出到當前終端屏幕,而並不會對原始文件做任何更改:
[root@svr5 ~]# sed '1,4d' rclocal.txt //刪除第1~4行,輸出結果
# want to do the full Sys V style init stuff.
touch /var/lock/subsys/local
[root@svr5 ~]# cat rclocal.txt //查看原始文本,並未改動
若希望直接修改文件內容,應添加選項 -i 。
比如,直接刪除rcloal.txt文件的第1~4行,不輸出結果:
[root@svr5 ~]# sed -i '1,4d' rclocal.txt //刪除操作
[root@svr5 ~]# cat rclocal.txt //確認刪除結果
下文中關於使用sed修改文件的示例中,為了避免大家在練習過程中因誤操作導致系統故障,部分命令省略 –i 選項,不再逐一說明。需要時,大家可自行加上此選項。
3)多個指令可以使用分號隔離
用分號來隔離多個操作(如果有定址條件,則應該使用{ }括起來),比如:
[root@svr5 ~]# sed -n '1p;4p' /etc/rc.local
#!/bin/sh
# You can put your own initialization stuff in here if you don't
或者:
[root@svr5 ~]# sed -n '{1p;4p}' /etc/rc.local
#!/bin/sh
# You can put your own initialization stuff in here if you don't
步驟二:認識sed工具的p輸出操作
先創建一個練習用的測試文件,每一行之前添加行號,方便練習時查看效果:
[root@svr5 ~]# cat -n /etc/rc.local > rclocal.txt
[root@svr5 ~]# cat rclocal.txt
1 #!/bin/sh
2 #
3 # This script will be executed *after* all the other init scripts.
4 # You can put your own initialization stuff in here if you don't
5 # want to do the full Sys V style init stuff.
6
7 touch /var/lock/subsys/local
1)輸出所有行,相當於cat命令。
[root@svr5 ~]# sed -n 'p' rclocal.txt
1 #!/bin/sh
2 #
3 # This script will be executed *after* all the other init scripts.
4 # You can put your own initialization stuff in here if you don't
5 # want to do the full Sys V style init stuff.
6
7 touch /var/lock/subsys/local
2)輸出第4行。
[root@svr5 ~]# sed -n '4p' rclocal.txt
4 # You can put your own initialization stuff in here if you don't
3)輸出第4~7行。
[root@svr5 ~]# sed -n '4,7p' rclocal.txt
4 # You can put your own initialization stuff in here if you don't
5 # want to do the full Sys V style init stuff.
6
7 touch /var/lock/subsys/local
4)輸出第4行和第7行。
[root@svr5 ~]# sed -n '4p;7p' rclocal.txt
4 # You can put your own initialization stuff in here if you don't
7 touch /var/lock/subsys/local
5)輸出第2行及之后的3行。
[root@svr5 ~]# sed -n '2,+3p' rclocal.txt
2 #
3 # This script will be executed *after* all the other init scripts.
4 # You can put your own initialization stuff in here if you don't
5 # want to do the full Sys V style init stuff.
6)輸出以local結尾的行。
[root@svr5 ~]# sed -n '/local$/p' rclocal.txt
7 touch /var/lock/subsys/local
7)輸出奇數行。
[root@svr5 ~]# sed -n 'p;n' rclocal.txt
1 #!/bin/sh
3 # This script will be executed *after* all the other init scripts.
5 # want to do the full Sys V style init stuff.
7 touch /var/lock/subsys/local
8)輸出偶數行。
[root@svr5 ~]# sed -n 'n;p' rclocal.txt
2 #
4 # You can put your own initialization stuff in here if you don't
6
9)從第5行輸出到最后一行。
[root@svr5 ~]# sed -n '5,$p' rclocal.txt
5 # want to do the full Sys V style init stuff.
6
7 touch /var/lock/subsys/local
10)輸出文本的行數。
[root@svr5 ~]# sed -n '$=' rclocal.txt
7
步驟三:認識sed工具的d輸出操作
還以rclocal.txt文件為例,文件內容如下所示:
[root@svr5 ~]# cat rclocal.txt
1 #!/bin/sh
2 #
3 # This script will be executed *after* all the other init scripts.
4 # You can put your own initialization stuff in here if you don't
5 # want to do the full Sys V style init stuff.
6
7 touch /var/lock/subsys/local
1)刪除第3~5行文本
[root@svr5 ~]# sed '3,5d' rclocal.txt
1 #!/bin/sh
2 #
6
7 touch /var/lock/subsys/local
2)刪除所有包含“init”的行
[root@svr5 ~]# sed '/init/d' rclocal.txt
1 #!/bin/sh
2 #
6
7 touch /var/lock/subsys/local
3)刪除所有包含“init”的行、所有包含“bin”的行
[root@svr5 ~]# sed '/init/d;/bin/d' rclocal.txt
2 #
6
7 touch /var/lock/subsys/local
4)刪除不包括“init”的行
[root@svr5 ~]# sed '/init/!d' rclocal.txt
3 # This script will be executed *after* all the other init scripts.
4 # You can put your own initialization stuff in here if you don't
5 # want to do the full Sys V style init stuff.
這個實際效果相當於只顯示包含“init”的行:
[root@svr5 ~]# sed -n '/init/p' rclocal.txt
3 # This script will be executed *after* all the other init scripts.
4 # You can put your own initialization stuff in here if you don't
5 # want to do the full Sys V style init stuff.
5)刪除文件的最后一行
[root@svr5 ~]# sed '$d' rclocal.txt
1 #!/bin/sh
2 #
3 # This script will be executed *after* all the other init scripts.
4 # You can put your own initialization stuff in here if you don't
5 # want to do the full Sys V style init stuff.
6
6)刪除文件中的空行
手動新建一個測試文件:
[root@svr5 ~]# vim blankline.txt
abc
def
hijklmn
hello world
I am here
end
刪除所有空行:
[root@svr5 ~]# sed '/^$/d' blankline.txt
abc
def
hijklmn
hello world
I am here
end
步驟四:認識sed工具的s替換操作
還以rclocal.txt文件為例,文件內容如下所示:
[root@svr5 ~]# cat rclocal.txt
1 #!/bin/sh
2 #
3 # This script will be executed *after* all the other init scripts.
4 # You can put your own initialization stuff in here if you don't
5 # want to do the full Sys V style init stuff.
6
7 touch /var/lock/subsys/local
1)將所有行中的第一個“ll”(如果有的話)替換為“TARENA”。
[root@svr5 ~]# sed 's/ll/TARENA/' rclocal.txt
1 #!/bin/sh
2 #
3 # This script wiTARENA be executed *after* all the other init scripts.
4 # You can put your own initialization stuff in here if you don't
5 # want to do the fuTARENA Sys V style init stuff.
6
7 touch /var/lock/subsys/local
2)將所有的“ll”(如果有的話)替換為“TARENA”。
[root@svr5 ~]# sed 's/ll/TARENA/g' rclocal.txt
1 #!/bin/sh
2 #
3 # This script wiTARENA be executed *after* aTARENA the other init scripts.
4 # You can put your own initialization stuff in here if you don't
5 # want to do the fuTARENA Sys V style init stuff.
6
7 touch /var/lock/subsys/local
3)將第3行內的第2個“script”替換為“SCRIPT”。
[root@svr5 ~]# sed '3s/script/SCRIPT/2' rclocal.txt
1 #!/bin/sh
2 #
3 # This script will be executed *after* all the other init SCRIPTs.
4 # You can put your own initialization stuff in here if you don't
5 # want to do the full Sys V style init stuff.
6
7 touch /var/lock/subsys/local
4)刪除文件內指定的字符串(替換為空)。
刪除所有的“init”字符串:
[root@svr5 ~]# sed 's/init//g' rclocal.txt
1 #!/bin/sh
2 #
3 # This script will be executed *after* all the other scripts.
4 # You can put your own ialization stuff in here if you don't
5 # want to do the full Sys V style stuff.
6
7 touch /var/lock/subsys/local
刪除所有的“script”、所有的“stuff”、所有的字母e,或者的關系用轉義方式 \| 來表示:
[root@svr5 ~]# sed 's/script\|stuff\|e//g' rclocal.txt
1 #!/bin/sh
2 #
3 # This will b xcutd *aftr* all th othr init s.
4 # You can put your own initialization in hr if you don't
5 # want to do th full Sys V styl init .
6
7 touch /var/lock/subsys/local
5)配置行的注釋、解除注釋。
以真實文件/etc/rc.local為例,文件內容如下:
[root@svr5 ~]# cat /etc/rc.local
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.
touch /var/lock/subsys/local
解除/etc/rc.local文件第3~5行的注釋(去掉開頭的 # ):
[root@svr5 ~]# sed '3,5s/^#//' /etc/rc.local
#!/bin/sh
#
This script will be executed *after* all the other init scripts.
You can put your own initialization stuff in here if you don't
want to do the full Sys V style init stuff.
touch /var/lock/subsys/local
將/etc/rc.local文件的第6~7行注釋掉(行首添加 # ):
[root@svr5 ~]# sed '6,7s/^/#/' /etc/rc.local
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.
#
#touch /var/lock/subsys/local
步驟五:利用sed完成本例要求的任務
參考數據文件內容如下:
[root@svr5 ~]# cat nssw.txt
An example Name Service Switch config file. This file should be
sorted with the most-used services at the beginning.
#
The entry '[NOTFOUND=return]' means that the search for an
entry should stop if the search in the previous entry turned
up nothing. Note that if the search failed due to some other reason
(like no NIS server responding) then the search continues with the
本小節的操作使用nssw.txt作為測試文件。
1)刪除文件中每行的第二個、最后一個字符
分兩次替換操作,第一次替換掉第2個字符,第二次替換掉最后一個字符:
[root@svr5 ~]# sed 's/.//2;s/.$//' nssw.txt
A example Name Service Switch config file. This file should b
srted with the most-used services at the beginning
#
Te entry '[NOTFOUND=return]' means that the search for a
etry should stop if the search in the previous entry turne
u nothing. Note that if the search failed due to some other reaso
(ike no NIS server responding) then the search continues with th
2)將文件中每行的第一個、第二個字符互換
每行文本拆分為“第1個字符”、“第2個字符”、“剩下的所有字符”三個部分,然后通過替換操作重排順序為“2-1-3”:
[root@svr5 ~]# sed -r 's/^(.)(.)(.*)/\2\1\3/' nssw.txt
nA example Name Service Switch config file. This file should be
osrted with the most-used services at the beginning.
#
hTe entry '[NOTFOUND=return]' means that the search for an
netry should stop if the search in the previous entry turned
pu nothing. Note that if the search failed due to some other reason
l(ike n up . Note that if the search failed due to some other
(like NIS server responding) then the search continues with
3)刪除文件中所有的數字、行首的空格
因原文件內沒有數字,行首也沒有空格,這里稍作做一點處理,生成一個新測試文件:
[root@svr5 ~]# sed 's/o/o7/;s/l/l4/;3,5s/^/ /' nssw.txt > nssw2.txt
[root@svr5 ~]# cat nssw2.txt
An exampl4e Name Service Switch co7nfig file. This file should be
so7rted with the most-used services at the beginning.
#
The entry '[NOTFOUND=return]' means that the search fo7r an
entry sho7ul4d stop if the search in the previous entry turned
up no7thing. Note that if the search fail4ed due to some other reason
(l4ike no7 NIS server responding) then the search continues with the
以nssw2.txt文件為例,刪除所有數字、行首空格的操作如下:
[root@svr5 ~]# sed -r 's/[0-9]//g;s/^( )+//' nssw2.txt
4)為文件中每個大寫字母添加括號
使用“&”可調用s替換操作中的整個查找串,所以可參考下列操作解決:
[root@svr5 ~]# sed 's/[A-Z]/(&)/g' nssw.txt
(A)n example (N)ame (S)ervice (S)witch config file. (T)his file should be
sorted with the most-used services at the beginning.
#
(T)he entry '[(N)(O)(T)(F)(O)(U)(N)(D)=return]' means that the search for an
entry should stop if the search in the previous entry turned
up nothing. (N)ote that if the search failed due to some other reason
(like no (N)(I)(S) server responding) then the search continues with the
2 案例2:使用sed修改系統配置
2.1 問題
本案例要求熟悉課上的sed應用案例,並編寫腳本anonftp.sh,實現以下功能:
通過yum安裝vsftpd軟件包
修改vsftpd服務配置,開啟匿名上傳
調整/var/ftp/pub目錄權限,允許ftp寫入
啟動vsftpd服務,並設置開機自運行
2.2 步驟
實現此案例需要按照如下步驟進行。
步驟一:認識課堂上的sed練習
1)修改默認運行級別
將默認運行級別修改為5,確認修改結果:
[root@svr5 ~]# sed -i '/^id:/s/3/5/' /etc/inittab
[root@svr5 ~]# grep "^id:" /etc/inittab
id:5:initdefault:
再改回去:
[root@svr5 ~]# sed -i '/^id:/s/5/3/' /etc/inittab
[root@svr5 ~]# grep "^id:" /etc/inittab
id:3:initdefault:
2)修改IP地址的網段部分,主機地址不變。
直接修改網卡eth0的配置文件,檢查原有的配置內容:
[root@svr5 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=none
HWADDR=00:0c:29:82:09:e9
ONBOOT=yes
NETMASK=255.255.255.0
IPADDR=192.168.4.4
TYPE=Ethernet
若希望將IP地址192.168.4.4修改為172.16.16.4,則應該定位到“IPADDR”所在的行,執行相應的替換(僅測試,尚未修改):
[root@svr5 ~]# sed '/^IPADDR/s/192.168.4.4/172.16.16.4/' \
/etc/sysconfig/network-scripts/ifcfg-eth0 | grep "^IPADDR"
IPADDR=172.16.16.4
要求只修改網段地址時,可以利用擴展正則表達式的 \1、\2、……等調用,分別對應此前第1個、第2個、…… 以 ()包圍的表達式所匹配的內容。
所以上述操作可以改為如下(啟用擴展匹配應添加 -r 選項):
[root@svr5 ~]# sed -r -i '/^IPADDR/s/192.168.4.(.*)/172.16.16.\1/' \
/etc/sysconfig/network-scripts/ifcfg-eth0
確認修改結果:
[root@svr5 ~]# grep "^IPADDR" /etc/sysconfig/network-scripts/ifcfg-eth0
IPADDR=172.16.16.4
再改回去:
[root@svr5 ~]# sed -r -i '/^IPADDR/s/172.16.16.(.*)/192.168.4.\1/' \
/etc/sysconfig/network-scripts/ifcfg-eth0
[root@svr5 ~]# grep "^IPADDR" /etc/sysconfig/network-scripts/ifcfg-eth0
IPADDR=192.168.4.4
3)調整httpd服務配置,更改網站根目錄
由於需要替換的字符串中有 / ,為了避免與sed替換操作的分隔混淆,可以使用其他字符作為替換分隔,比如可改用“s#old#new#”的方式實現替換:
[root@svr5 ~]# sed -i 's#/var/www/html#/opt/wwwroot#' \
/etc/httpd/conf/httpd.conf
[root@svr5 ~]# grep "^DocumentRoot" /etc/httpd/conf/httpd.conf
DocumentRoot "/opt/wwwroot"
若要恢復,可再改回去:
[root@svr5 ~]# sed -i 's#/opt/wwwroot#/var/www/html#'\
/etc/httpd/conf/httpd.conf
[root@svr5 ~]# grep "^DocumentRoot" /etc/httpd/conf/httpd.conf
DocumentRoot "/var/www/html"
步驟二:編寫anonftp.sh腳本,用來裝配匿名FTP服務
1)任務需求及思路分析
vsftpd服務的安裝、改目錄權限、起服務等操作可以直接寫在腳本中。
修改vsftpd.conf配置的工作可以使用sed命令,根據默認配置,只需要定位到以#anon開頭的行,去掉開頭的注釋即可。
2)根據實現思路編寫腳本文件
[root@svr5 ~]# vim anonftp.sh
#!/bin/bash
yum -y install vsftpd //安裝vsftpd軟件
cp /etc/vsftpd/vsftpd.conf{,.bak} //備份默認的配置文件
sed -i "/^#anon/s/^#//" /etc/vsftpd/vsftpd.conf //修改服務配置
chown ftp /var/ftp/pub //調整目錄權限
/etc/init.d/vsftpd restart //啟動服務
chkconfig vsftpd on //設為自動運行
[root@svr5 ~]# chmod +x anonftp.sh
3)驗證、測試腳本
運行腳本anonftp.sh:
[root@svr5 ~]# ./anonftp.sh
.. ..
Installed:
vsftpd.x86_64 0:2.0.5-28.el5
Complete!
關閉 vsftpd: [失敗]
為 vsftpd 啟動 vsftpd: [確定]
使用ftp登錄服務,測試是否可以上傳:
[root@svr5 ~]# ftp localhost //本機訪問測試
Connected to localhost.localdomain.
220 (vsFTPd 2.0.5)
530 Please login with USER and PASS.
530 Please login with USER and PASS.
KERBEROS_V4 rejected as an authentication type
Name (localhost:root): ftp //匿名登錄
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> cd pub //切換到 pub/ 目錄
250 Directory successfully changed.
ftp> put install.log //上傳當前目錄下的install.log 文件
local: install.log remote: install.log
227 Entering Passive Mode (127,0,0,1,192,127)
150 Ok to send data.
226 File receive OK.
33139 bytes sent in 0.0065 seconds (5e+03 Kbytes/s)
ftp> quit //斷開FTP連接
221 Goodbye.
查看/var/ftp/pub新上傳的文件:
[root@svr5 ~]# ls -lh /var/ftp/pub/
總計 36K
-rw------- 1 ftp ftp 33K 12-13 18:25 install.log
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工具的多行文本處理操作:
i:在指定的行之前插入文本
a:在指定的行之后追加文本
c:替換指定的行
3.3 步驟
實現此案例需要按照如下步驟進行。
步驟一:修改主機名配置文件
1)確認修改前的配置
[root@svr5 ~]# cat /etc/sysconfig/network
NETWORKING=yes
HOSTNAME=svr5.tarena.com
2)使用sed修改主機名配置所在行的內容(c整行替換)
[root@svr5 ~]# sed '/^HOSTNAME/cHOSTNAME=mysvr.tarena.com' /etc/sysconfig/network
步驟二:修改hosts文件,添加新的記錄
1)確認修改前的配置
[root@svr5 ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
2)使用sed修改hosts文件,添加兩行新紀錄(a追加)
[root@svr5 ~]# sed -i '$a192.168.4.5 svr5.tarena.com svr5\
> 119.75.217.56 www.baidu.com' /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
119.75.217.56 www.baidu.com
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腳本
[root@svr5 ~]# vim ./getupwd.sh
#/bin/bash
> /tmp/getupwd.log ## 創建空文件
sed -n '/:\/bin\/bash$/w /tmp/urec.tmp' /etc/passwd ## 提取符合條件的賬號記錄
UNUM=$(egrep -c '.' /tmp/urec.tmp) ## 取得記錄個數
while [ ${i:=1} -le $UNUM ] ## 從第1行開始,遍歷賬號記錄
do
UREC=$(sed -n "${i}p" /tmp/urec.tmp) ## 取指定行數的記錄
NAME=${UREC%%:*} ## 截取用戶名(記錄去尾)
PREC=$(sed -n "/^$NAME:/p" /etc/shadow) ## 查找與用戶名對應的密碼記錄
PASS=${PREC#*:} ## 掐頭
PASS=${PASS%%:*} ## 去尾,只留下密碼記錄
echo "$NAME --> $PASS" >> /tmp/getupwd.log ## 保存結果
let i++ ## 自增1,轉下一次循環
done
/bin/rm -rf /tmp/urec.tmp ## 刪除臨時文件
echo "用戶分析完畢,請查閱文件 /tmp/getupwd.log" ## 完成后提示
[root@svr5 ~]# chmod +x ./getupwd.sh
步驟二:測試、驗證執行結果
[root@svr5 ~]# ./getupwd.sh
用戶分析完畢,請查閱文件 /tmp/getupwd.log
[root@svr5 ~]# less /tmp/getupwd.log
root --> $6$IWgMYmRACwdbfwBo$dr8Yn983nswiJVw0dTMjzbDvSLeCd1GMYjbvsDiFEkL8jnXOLcocBQypOCr4C6BRxNowIxjh6U2qeFU0u1LST/
zengye --> $6$Qb37LOdzRl5995PI$L0zTOgnhGz8ihWkW81J.5XhPp/l7x2./Me2ag0S8tRndCBL9nIjHIKkUKulHxJ6TXyHYmffbVgUT6pbSwf8O71
clamav --> !!
mysql --> !!
abc --> !!
.. ..
從上述參考腳本可以發現,使用sed來實現字段提取會比較復雜。下一章課程將會學到awk命令,屆時可以通過更簡單的方法來改進此腳本內容。
