======博主所學知識來著於恩師馬哥的親授======
馬哥教育“2014夏令營”開始啦!!!馬哥教育是目前性價比最高的Linux培訓,國內好評度排名第一,並被網友稱為Linux界的"黃埔軍校",全部課程採用Centos6.5x86_64講解,經過幾期網路班的總結和錘鍊,逐漸完善的課程體系,學員學習進度監督和優質的考試系統檢驗學員掌握程度,活躍的線上答疑環節,名師陪伴,牛人指點,精彩不容錯過。
詳情猛戳:http://www.magedu.com/
課程內容:http://www.magedu.com/mentuqc
網路班一體化服務:http://mageedu.blog.51cto.com/4265610/1379598
============================================
文本處理工具之二 sed命令詳解
sed:Stream Editor文字資料流編輯,sed是一個“非互動”面向字元流的編輯器。能同時處理多個檔案多行的內容,可以不對原檔案改動,把整個檔案輸入到螢幕,可以把只匹配到模式的內容輸入到螢幕上。還可以對原檔案改動,但是不會再螢幕上返回結果。
sed命令的文法格式:
sed的命令格式: sed [option] 'sed command'filename
sed的指令碼格式:sed [option] -f 'sed script'filename
sed命令的選項(option):
-n :只列印模式比對的行
-e :直接在命令列模式上進行sed動作編輯,此為預設選項
-f :將sed的動作寫在一個檔案內,用–f filename 執行filename內的sed動作
-r :支援擴充運算式
-i :直接修改檔案內容
sed在檔案中查詢文本的方式:
1)使用行號,可以是一個簡單數字,或是一個行號範圍
x |
x為行號 |
x,y |
表示行號從x到y |
/pattern |
查詢包含模式的行 |
/pattern /pattern |
查詢包含兩個模式的行 |
pattern/,x |
在給定行號上查詢包含模式的行 |
x,/pattern/ |
通過行號和模式查詢匹配的行 |
x,y! |
查詢不包含指定行號x和y的行 |
2)使用Regex、擴充Regex(必須結合-r選項)
^ |
錨點行首的合格內容,用法格式"^pattern" |
$ |
錨點行首的合格內容,用法格式"pattern$" |
^$ |
空白行 |
. |
匹配任意單個字元 |
* |
匹配緊挨在前面的字元任意次(0,1,多次) |
.* |
匹配任意長度的任一字元 |
\? |
匹配緊挨在前面的字元0次或1次 |
\{m,n\} |
匹配其前面的字元至少m次,至多n次 |
\{m,\} |
匹配其前面的字元至少m次 |
\{m\} |
精確匹配前面的m次\{0,n\}:0到n次 |
\< |
錨點詞首----相當於 \b,用法格式:\<pattern |
\> |
錨點詞尾,用法格式:\>pattern |
\<pattern\> |
單詞錨點 |
\(\) |
分組,用法格式:\(pattern\),引用\1,\2 |
[] |
匹配指定範圍內的任意單個字元 |
[^] |
匹配指定範圍外的任意單個字元 |
[:digit:] |
所有數字, 相當於0-9, [0-9]---> [[:digit:]] |
[:lower:] |
所有的小寫字母 |
[:upper:] |
所有的大寫字母 |
[:alpha:] |
所有的字母 |
[:alnum:] |
相當於0-9a-zA-Z |
[:space:] |
空白字元 |
[:punct:] |
所有標點符號 |
#######sed的匹配模式支援Regex#####################sed'5 q'/etc/passwd#列印前5行sed-n '/r*t/p'/etc/passwd#列印匹配r有0個或者多個,後接一個t字元的行sed-n '/.r.*/p'/etc/passwd#列印匹配有r的行並且r後面跟任一字元sed-n '/o*/p'/etc/passwd#列印o字元重複任意次sed-n '/o\{1,\}/p'/etc/passwd#列印o字重複出現一次以上sed-n '/o\{1,3\}/p'/etc/passwd#列印o字重複出現一次到三次之間以上
sed的編輯命令(sed command):
p |
列印匹配行(和-n選項一起合用) |
= |
顯示檔案行號 |
a\ |
在定位行號後附加新文本資訊 |
i\ |
在定位行號後插入新文本資訊 |
d |
刪除定位行 |
c\ |
用新文本替換定位文本 |
w filename |
寫文本到一個檔案,類似輸出重新導向 > |
r filename |
從另一個檔案中讀文本,類似輸入重新導向 < |
s |
使用替換模式替換相應模式 |
q |
第一個模式比對完成後退出或立即退出 |
l |
顯示與八進位ACSII代碼等價的控制符 |
{} |
在定位行執行的命令組,用分號隔開 |
n |
從另一個檔案中讀文本下一行,並從下一條命令而不是第一條命令開始對其的處理 |
N |
在資料流中添加下一行以建立用於處理的多行組 |
g |
將模式2粘貼到/pattern n/ |
y |
傳送字元,替換單個字元 |
對檔案的操作無非就是”增刪改查“,怎樣用sed命令實現對檔案的”增刪改查“,玩轉sed是寫自動化指令碼必須的基礎之一。
sed命令列印檔案資訊(查詢):
####用sed列印檔案的資訊的例子的命令######sed -n '/^#/!p' /etc/vsftpd/vsftpd.conf sed -n '/^#/!{/^$/!p}' /etc/vsftpd/vsftpd.confsed -e '/^#/d' -e '/^$/d' /etc/vsftpd/vsftpd.confsed -n '1,/adm/p' /etc/passwdsed -n '/adm/,6p' /etc/passwdsed -n '/adm/,4p' /etc/passwdsed -n '/adm/,2p' /etc/passwd###以片是對這些sed命令例子的解釋和顯示結果
sed命令實現對檔案內容的添加:(對源檔案添加的話就用-i參數):
####sed命令可以實現的添加#######1)匹配行的行首添加,添加在同行#2)匹配行的行中的某個字元後添加#3)匹配行的行尾添加字元#4)匹配行的行前面行添加#5)匹配行的行後面行添加#6)檔案的行首添加一行 [root@jie1 ~]# sed -i '1 i\sed command start' myfile#7)檔案的行尾追加一行 [root@jie1 ~]# sed -i '$a \sed command end' myfile
sed命令實現對檔案內容的刪除:(對源檔案直接刪除用-i參數):
sed的刪除操作是針對檔案的行,如果想刪除行中的某個字元,那就用替換(別急,替換稍後就講,而且替換是sed最常用的)
重點:sed命令實現對檔案內容的替換(替換是在shell自動化指令碼中用到最多的操作)
#================源檔案裡面的內容===============================[root@jie1 ~]# cat testanonymous_enable=YESwrite_enable=YESlocal_umask=022xferlog_enable=YESconnect_from_port_20=YESroot:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologinDEVICE="eth0"BOOTPROTO="static"HWADDR="00:0C:29:90:79:78"ONBOOT="yes"IPADDR=172.16.22.1NETMASK=255.255.0.0#======================================================================[root@jie1 ~]# sed -i '/DEVICE/c\Ethernet' test #匹配DEVICE的行,替換成Ethernet這行[root@jie1 ~]# sed -i 's/static/dhcp/' test #把static替換成dhcp(/,@,#都是前面所說的地址定界符)[root@jie1 ~]# sed -i '/IPADDR/s@22\.1@10.12@' test #匹配IPADDR的行,把22.1替換成10.12由於.號有特殊意義所有需要轉義[root@jie1 ~]# sed -i '/connect/s#YES#NO#' test #匹配connect的行,把YES替換成NO[root@jie1 ~]# sed -i 's/bin/tom/2g' test #把所有匹配到bin的行中第二次及第二次之後出現bin替換成tom[root@jie1 ~]# sed -i 's/daemon/jerry/2p' test #把所有匹配到bin的行中第二次出現的daemon替換成jerry,並在生產與匹配行同樣的行[root@jie1 ~]# sed -i 's/adm/boss/2' test #把所有匹配到adm的行中僅僅只是第二次出現的adm替換成boss[root@jie1 ~]# sed -i '/root/{s/bash/nologin/;s/0/1/g}' test #匹配root的行,把bash替換成nologin,且把0替換成1[root@jie1 ~]# sed -i 's/root/(&)/g' test #把root用括弧括起來,&表示引用前面匹配的字元[root@jie1 ~]# sed -i 's/BOOTPROTO/#BOOTPROTO/' test #匹配BOOTPROTO替換成#BOOTPROTO,在設定檔中一般用於注釋某行[root@jie1 ~]# sed -i 's/ONBOOT/#&/' test #匹配ONBOOT的行的前面添加#號,在設定檔中也表示注釋某行[root@jie1 ~]# sed -i '/ONBOOT/s/#//' test #匹配ONBOOT的行,把#替換成空,即去掉#號,也一般用作去掉#注釋#================執行以上sed命令之後檔案顯示的內容====================[root@jie1 ~]# cat testanonymous_enable=YESwrite_enable=YESlocal_umask=022xferlog_enable=YESconnect_from_port_20=NO(root):x:1:1:(root):/(root):/bin/nologinbin:x:1:1:tom:/tom:/stom/nologindaemon:x:2:2:jerry:/sbin:/stom/nologindaemon:x:2:2:jerry:/sbin:/stom/nologinadm:x:3:4:boss:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologinEthernet#BOOTPROTO="dhcp"HWADDR="00:0C:29:90:79:78"ONBOOT="yes"IPADDR=172.16.10.12NETMASK=255.255.0.0
sed引用變數:(在自動化shell指令碼 中也經常會使用到變數)
第一種當sed命令裡面沒有預設的變數時可以把單引號改成雙引號;
第二種當sed命令裡面有預設的變數時,那自己定義的變數需要加單引號,且sed裡面的語句必須用單引
[root@jie1 ~]# cat >> myfile << EOF> hello world> i am jie> how are you> EOF #先產生一個檔案[root@jie1 ~]# cat myfilehello worldi am jiehow are you[root@jie1 ~]# name=li #定義一個變數,且給變數賦值[root@jie1 ~]# sed -i "s/jie/$name/" myfile #把匹配jie的字元替換成變數的值[root@jie1 ~]# cat myfilehello worldi am lihow are you[root@jie1 ~]# sed -i "$a $name" myfile #當sed命令也有預設變數時,在去引用自己定義的變數會出現語法錯誤sed: -e expression #1, char 3: extra characters after command[root@jie1 ~]# sed -i '$a '$name'' myfile #在引用自訂的變數時,sed語句必須用單引引住,然後把自訂的變數也用單引號引住[root@jie1 ~]# cat myfilehello worldi am lihow are youli[root@jie1 ~]#
sed的其它進階使用:
1)把正在用sed操作的檔案的內容寫到例外一個檔案中
[root@jie1 ~]# cat test #sed操作的檔案中的內容Ethernet#BOOTPROTO="dhcp"HWADDR="00:0C:29:90:79:78"ONBOOT="yes"IPADDR=172.16.10.12NETMASK=255.255.0.0[root@jie1 ~]# sed -i 's/IPADDR/ip/w ip.txt' test #把sed操作的檔案內容儲存到另外一個檔案中,w表示儲存,ip.txt檔案名稱[root@jie1 ~]# cat ip.txt #查看新檔案的內容ip=172.16.10.12[root@jie1 ~]#
2)讀取一個檔案到正在用sed操作的檔案中
[root@jie1 ~]# cat myfile #檔案內容hello worldi am lihow are youli[root@jie1 ~]# cat test #將用sed操作的檔案的內容Ethernet#BOOTPROTO="dhcp"HWADDR="00:0C:29:90:79:78"ONBOOT="yes"IPADDR=172.16.10.12NETMASK=255.255.0.0[root@jie1 ~]# sed -i '/Ethernet/r myfile' test #在匹配Ethernet的行,讀進來另一個檔案的內容,讀進來的檔案的內容會插入到匹配Ethernet的行後[root@jie1 ~]# cat test #再次查看用sed命令操作的行Ethernethello worldi am lihow are youli#BOOTPROTO="dhcp"HWADDR="00:0C:29:90:79:78"ONBOOT="yes"IPADDR=172.16.10.12NETMASK=255.255.0.0[root@jie1 ~]#
sed的經典例子:
##1)、處理以下檔案內容,將網域名稱取出並進行計數排序,如處理:http://www.baidu.com/index.htmlhttp://www.baidu.com/1.htmlhttp://post.baidu.com/index.htmlhttp://mp3.baidu.com/index.htmlhttp://www.baidu.com/3.htmlhttp://post.baidu.com/2.html得到如下結果:網域名稱的出現的次數 網域名稱3 www.baidu.com2 post.baidu.com1 mp3.baidu.com[root@localhost shell]# cat file | sed -e ' s/http:\/\///' -e ' s/\/.*//' | sort | uniq -c | sort -rn3 www.baidu.com2 post.baidu.com1 mp3.baidu.com[root@codfei4 shell]# awk -F/ '{print $3}' file |sort -r|uniq -c|awk '{print $1"\t",$2}'3 www.baidu.com2 post.baidu.com1 mp3.baidu.com##2)、用grep結合sed取出網卡的ip地址[root@jie1 ~]# ifconfig | grep -B1 "inet addr" |grep -v "\-\-" |sed -n -e 'N;s/\(eth[0-9]\).*\n.*addr:\([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\).*/\1 \2/p'
學會sed的使用是寫自動化shell指令碼的基礎,sed也是一個非常有用且重要的命令,是文本處理工具之一,以上是我自己學習總結的sed命令簡單的用法,sed還有更進階的用法,也還在學習中。