天天看點

Shell腳本----三劍客指令(grep、sed、awk)正規表達式grepsedawk

三劍客指令

  • 正規表達式
      • 基礎正規表達式元字元
      • 拓展元字元
  • grep
  • sed
  • awk
      • 内建變量

正規表達式

了解三劍客指令前得了解正規表達式,正規表達式是運用三劍客指令的基本文法

基礎正規表達式元字元

- \  :轉義字元,用于取消特殊符号的含義,如:\!、\$
 - ^ :比對字元串開始的位置,如:^root 比對以root開頭的行,
 - $ :比對字元串結束的位置,如:world$比對以world結尾的行
 - . :比對除\n外的任意一個字元
 - * :比對前面的子表達式0次或者多次
 - [  ] : 比對[   ]中的一個字元,如:[0-9]比對任意一個數字
 - [^] :比對不在[  ]中的任意一個字元,如:[^0-9]比對任意一個非數字字元
 - \{n\} :比對前面子表達式n次,如:[0-9]\{2\}比對兩位數字
 - \{n,m\} :比對前面的子表達式n到m次,如:[a-z]\{2,3\}表示比對兩到三位小寫字母
 - \{n,\} :比對前面的子表達式不少于n次,如:[0-9]\{2,\}表示兩位及兩位以上數字
 - \< : 比對以……開頭的行
 - \> : 比對以……結尾的行
 - \<……\> : 比對某一個單詞的行
           

拓展元字元

- + ;比對前一個字元1個或多個,如:go+d,将比對至少一個o
 - ? :比對0個或1個字元,如:go?d,将比對到gd或god
 - | :或
 - () : 将括号中的字元串作為一個整體
 - {n} : 前一個字元重複n次
 - {n,} : 前一個字元至少重複n次
 - {n,m} : 前一個字元出現n-m次
           

grep

grep指令使用選項規則

grep -v “text” :過濾掉包含text的内容檢視剩下的檔案内容
grep “text” :檢視檔案中包含text的行
grep “^q” :檢視檔案中以q開頭的内容
grep “g$” :檢視以g結尾的檔案内容
grep “q*” :這裡*代表前面一個字母出現0次或多次
grep -v “^$” :過濾掉檔案裡的空行
grep “[rR]oot” :[]裡表示R或r的字母,相當于查找包含root或Root的檔案内容
grep -E “^root|Root$” 檔案 :-E代表引入正則,這裡的|代表或的意思,這條指令表示查找以root開頭Root結尾的檔案内容
grep -E也可以直接寫egrep
grep -c :顯示有幾行
grep -w “text” :隻找text這個單詞的檔案内容
grep -i  :忽略大小寫檢視檔案内容
grep -o “text”  :隻以行顯示text這個字元
           
[[email protected] ww]# grep root /etc/passwd            //比對檔案中包含root的行
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[[email protected] ww]# grep ^root /etc/passwd           //比對檔案中以root開頭的行
root:x:0:0:root:/root:/bin/bash
[[email protected] ww]# grep bash$ /etc/passwd           //比對檔案中以bash結尾的行
root:x:0:0:root:/root:/bin/bash
whd:x:1000:1000:whd:/home/whd:/bin/bash
lisi:x:1001:1001::/home/lisi:/bin/bash
[[email protected] ww]# grep 'r..d' /etc/passwd          //比對r和d之間有兩個任意字元的行
adm:x:3:4:adm:/var/adm:/sbin/nologin
[[email protected] ww]# grep '[^s]bin' /etc/passwd       //比對bin前面不是s的行
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
whd:x:1000:1000:whd:/home/whd:/bin/bash
[[email protected] ww]# grep '4\{1,\}' /etc/passwd       //比對數字4出現1次及以上的行
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
colord:x:997:994:User for colord:/var/lib/colord:/sbin/nologin
unbound:x:994:989:Unbound DNS resolver:/etc/unbound:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
setroubleshoot:x:990:984::/var/lib/setroubleshoot:/sbin/nologin
gdm:x:42:42::/var/lib/gdm:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
username3:x:1004:1004::/home/username3:/bin/bash
username4:x:1005:1005::/home/username4:/bin/bash
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
[[email protected] ww]# grep -e "ntp" -e "root" /etc/passwd     //-e參數比對多個條件
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
[[email protected] ww]# grep '^[a-z]ae' /etc/passwd         //比對ae前面是小寫字母開頭的行
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[[email protected] ww]# grep '[^a-z]ae' /etc/passwd         //比對ae前面不是小寫字母的行
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
pulse:x:171:171:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
           

sed

Sed是文本處理工具,依賴于正規表達式,重要用于蘇互動式替換修改檔案,可以對文本内容進行增删改查,sed在處理資料時預設不修改檔案内容,而是把目前處理的行存儲在臨時緩沖區中,所有指令都在緩沖區中操作,處理完成後把緩沖區内容預設輸出到螢幕
set -e ‘編輯指令’ 檔案名 :指定要執行的指令,
set -n ‘編輯指令’ 檔案名 :隻輸出處理後的行,讀入時不顯示
set -i ‘編輯指令’ 檔案名 :直接編輯檔案,而不輸出結果
set -r :使用拓展型正規表達式的文法
           

編輯指令中的選項參數:

p :列印指定的行
  d :删除指定的行
  s :字串替換,格式: “行範圍s/原字元串/新字元串/g”
  g :表示隻要符合條件,全部進行處理
  r :可以将另一個檔案内容讀取到檔案中
  w :可以将另一個檔案内容覆寫到檔案中
  i :插入,在目前行上面插入一行或多行
  a :插入,在目前行後面插入一行或多行
  c :将標明行替換成指定内容
  y :字元轉換
           
[[email protected] ww]# sed -n 'p' /etc/passwd        //列印檔案所有内容,sed後一般跟-n結合,不加-n相當于把檔案内容和緩沖中都列印,相當于列印兩次
[[email protected] ww]# sed -n '3p' /etc/passwd       //列印檔案第三行内容
[[email protected] ww]# sed -n '1,3p' /etc/passwd     //列印1到3行的内容
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[[email protected] ww]# sed -n '$p' /etc/passwd       //列印最後一行内容
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
[[email protected] ww]# sed -n '1,+3p' /etc/passwd    //列印第一行開始加3行内容
root:x:0:0:root:/root:/bin/bash
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
[[email protected] ww]# sed -n '/^$/p' 檔案名    //列印空行
[[email protected] ww]# sed -n '/ /p' 檔案名     //列印有空格的行
[[email protected] ww]# sed -n '/root/=' /etc/passwd      //顯示包含root行的行号 
1
10
[[email protected] ww]# sed -n '$=' /etc/passwd           //檢視檔案有多少行
56
[[email protected] ww]# sed -e '3q' /etc/passwd           //輸出前5行後退出
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[[email protected] ~]# sed -n '1a hello world' /etc/passwd    //在第一行後面添加一行為hello world
[[email protected] ~]# sed -n '3i hello' /etc/passwd           //在第三行前面添加一行為hello
           
[[email protected] ~]# sed -n '3d' /etc/passwd          //删除第三行
[[email protected] ~]# sed -n '2,4d' /etc/passwd        //删除第2到第4行
[[email protected] ~]# sed -n '$d' /etc/passwd          //删除最後一行
[[email protected] ~]# sed -n '/root/!d' /etc/passwd    //删除不包含root的行
[[email protected] ~]# sed -n '/^root/d' /etc/passwd    //删除以root開頭的行
           
[[email protected] ww]# cat -n /etc/passwd | sed -n '1~8p'   //從第一行開始每隔8行列印檔案内容
     1	root:x:0:0:root:/root:/bin/bash
     9	mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    17	libstoragemgmt:x:998:995:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin
    25	radvd:x:75:75:radvd user:/:/sbin/nologin
    33	geoclue:x:992:986:User for geoclue:/var/lib/geoclue:/sbin/nologin
    41	avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
    49	username4:x:1005:1005::/home/username4:/bin/bash
[[email protected] ww]# cat -n /etc/passwd | sed -n 'p;n'        //輸出所有奇數行
     1	root:x:0:0:root:/root:/bin/bash
     3	daemon:x:2:2:daemon:/sbin:/sbin/nologin
     5	lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
     7	shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
     9	mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    11	games:x:12:100:games:/usr/games:/sbin/nologin
    13	nobody:x:99:99:Nobody:/:/sbin/nologin
    15	dbus:x:81:81:System message bus:/:/sbin/nologin
    	………………………………
[[email protected] ww]# cat -n /etc/passwd | sed -n 'n;p'         //輸出所有偶數行
     2	bin:x:1:1:bin:/bin:/sbin/nologin
     4	adm:x:3:4:adm:/var/adm:/sbin/nologin
     6	sync:x:5:0:sync:/sbin:/bin/sync
     8	halt:x:7:0:halt:/sbin:/sbin/halt
    10	operator:x:11:0:operator:/root:/sbin/nologin
    12	ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    14	systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
		………………………………
[[email protected] ww]# cat -n /etc/passwd | sed -n '10,${n;p}'    //輸出從10行開始到結尾的奇數行  
    11	games:x:12:100:games:/usr/games:/sbin/nologin
    13	nobody:x:99:99:Nobody:/:/sbin/nologin
    15	dbus:x:81:81:System message bus:/:/sbin/nologin
    17	libstoragemgmt:x:998:995:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin
    19	rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
    21	saslauth:x:995:76:Saslauthd user:/run/saslauthd:/sbin/nologin
           
[[email protected] ww]# sed -n '/root\|ntp/p' /etc/passwd      //輸出包含root或ntp的行,這裡|時拓展正則,需要\轉義
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin 
[[email protected] ww]# sed -n '/root/p' /etc/passwd            //輸出包含root的行
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[[email protected] ww]# sed -n '/root/Ip' /etc/passwd           //不區分大小寫顯示含root的行 
[[email protected] ww]# sed -nr '/root|ntp/p' /etc/passwd       //輸出包含root或ntp的行,不用\轉義|的話要在前面加r
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
           
[[email protected] ww]#sed  's/root//g' /etc/passwd			//将檔案中所有的root都删除
[[email protected] ww]#sed  's#/bin/bash#hello#p' /etc/passwd   //将檔案中的/bin/bash替換成hello。這裡的#表示分隔符,可以換成@,逗号,或者\
[[email protected] ww]#sed  '/root/s/root/ROOT/g' /etc/passwd    //将包含root行的root都替換成ROOT
[[email protected] ww]#sed 's/$/ABC/g'  /etc/passwd           //在每行的末尾添加ABC
[[email protected] ww]#sed  '/root/s/^/#/g'  /etc/passwd        //在包含root的行開頭添加#
[[email protected] ww]#sed '/root/w file2' /etc/passwd            //将包含root的行寫入file2中,覆寫寫入
[[email protected] ww]#sed '1,5 {H;d};$G' /etc/passwd             //将1到5行内容遷移到末尾
[[email protected] ~]# echo hello world gg | sed -nr 's/(hello) (world) (gg)/\2 \1 \3/p'
world hello gg
##### 将hello和world換位列印,注意三個參數之間跟前面的一樣有空格,後面的數字表示将前面的()整體對應的位置
[[email protected] ~]# echo hello world gg | sed -nr 's/(hello) (world)/\1 the \2/p'
hello the world gg
#####  在hello和world中插入the
           
[[email protected] ww]#set -i 's/^/#/' /etc/passwd               //在每行開頭添加#,直接修改源檔案内容
[[email protected] ww]#set -i 's/^/#//' /etc/passwd           //删除每行開頭的#,直接修改源檔案
           
[[email protected] ~]# vim sed.sh
#!/bin/sed -f
#在腳本中直接使用sed,這裡的指令序列不用加單引号,每行最後一個字元不能存在其它字元
s/root/ROOT/g
s/\/sbin\/nologin/xxx/g
[[email protected] ~]# sed -f sed.sh pp.bak 
 ROOT:x:0:0:ROOT:/ROOT:/bin/bash
bin:x:1:1:bin:/bin:xxx
daemon:x:2:2:daemon:/sbin:xxx
adm:x:3:4:adm:/var/adm:xxx
lp:x:4:7:lp:/var/spool/lpd:xxx
sync:x:5:0:sync:/sbin:/bin/sync                       
           

awk

格式 :awk 選項 指令部分
awk '{print}' 檔案名 :列印檔案所有内容
awk '{print "'$變量名'"}'  :引入awk外部變量
           

内建變量

  • NF :顯示列數
  • NR :顯示行号
  • $0 :處理整行内容
  • $n :這裡n是一個數字,表示處理第n列内容
  • FS :指定分隔符
  • OFS :指定輸出時文本列之間的連接配接符
  • RS :指定每行之間的分隔,如:RS : ,表示在冒号那裡就會分行
  • ORS :指定每行之間連接配接型
[[email protected] ~]# awk '{print}' pp.bak        //列印檔案所有内容,這裡的pp.bak檔案内容是複制/etc/passwd檔案的前幾行
root:x:0:0:root:/root:/bin/bash
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
sync:x:5:0:sync:/sbin:/bin/sync
           
  1. -F指定分隔符,$1表示列印第一列
[[email protected] ~]# awk -F: '{print $1}' pp.bak      
root
bin
daemon
adm
lp
sync
[[email protected] ~]# awk -F: '{print $0}' pp.bak      //$0表示列印整行
root:x:0:0:root:/root:/bin/bash
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
sync:x:5:0:sync:/sbin:/bin/sync
           
  1. 以冒号為分隔符列印第一列第二列
[[email protected] ~]# awk -F: '{print $1,$2}' pp.bak     
root x
bin x
daemon x
adm x
lp x
sync x
           
  1. 用引号引起可以輸出常量
[[email protected] ~]# awk -F: '{print $1"hhh"$2}' pp.bak 
roothhhx
binhhhx
daemonhhhx
admhhhx
lphhhx
synchhhx
hhh
           
  1. 輸出“使用者名的uid是:”這裡的使用者名是變量,uid也是變量,使用者名在第一列,uid在第三列
[[email protected] ~]# awk -F: '{print "使用者名"$1"的uid是"$3}' pp.bak 
使用者名root的uid是0
使用者名bin的uid是1
使用者名daemon的uid是2
使用者名adm的uid是3
使用者名lp的uid是4
使用者名sync的uid是5
           
  1. 以冒号為分隔符檢視每行有多少列
[[email protected] ~]# awk -F: '{print NF}' pp.bak 
7
7
7
7
7
7
[[email protected] ~]# awk -F: '{print $NF}' pp.bak   
####  NF前加$表示顯示最後一列,可以了解為先NF顯示每行的列數,然後以這列數列印,就相當于列印每行的最後一列
/bin/bash
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
/bin/sync
           
  1. NR列印行号
[[email protected] ~]# awk -F: '{print NR}' pp.bak 
1
2
3
4
5
6
[[email protected] ~]# awk -F: '{print NR,$0}' pp.bak    //顯示行号列印所有内容
1 root:x:0:0:root:/root:/bin/bash
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
6 sync:x:5:0:sync:/sbin:/bin/sync
[[email protected] ~]# awk -F: '{print NR"\t"$0}' pp.bak      //  \t表示制表符,也相當于tab鍵
1	root:x:0:0:root:/root:/bin/bash
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
6	sync:x:5:0:sync:/sbin:/bin/sync
           
  1. awk還可以增加條件判斷
[[email protected] ~]# awk -F: '/^bin/{print}' pp.bak          //列印以bin開頭的,
bin:x:1:1:bin:/bin:/sbin/nologin
[[email protected] ~]# awk -F: '/bin/{print}' pp.bak           //列印包含bin的
root:x:0:0:root:/root:/bin/bash
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
sync:x:5:0:sync:/sbin:/bin/sync
[[email protected] ~]# awk -F: '$1~/bin/{print $NF}' pp.bak 
####  模糊比對第一列裡含bin的行并列印其最後一列,在~前面加!表示不比對含bin的行
/sbin/nologin
[[email protected] ~]# awk -F: 'NR==1{print $NF}' pp.bak       //列印第一行的最後一列
/bin/bash
[[email protected] ~]# awk -F: '$1=="lp"{print $NF}' pp.bak    //列印第一列中包含lp的行的最後一列
/sbin/nologin
[[email protected] ~]# awk -F: 'NR~/3/{print NR,$0}' /etc/shadow      //列印含3行号的内容
3 daemon:*:17834:0:99999:7:::
13 nobody:*:17834:0:99999:7:::
23 rtkit:!!:18779::::::
30 qemu:!!:18779::::::
31 tss:!!:18779::::::
32 usbmuxd:!!:18779::::::
33 geoclue:!!:18779::::::
34 ntp:!!:18779::::::
35 sssd:!!:18779::::::
36 setroubleshoot:!!:18779::::::
37 saned:!!:18779::::::
38 gdm:!!:18779::::::
39 gnome-initial-setup:!!:18779::::::
43 tcpdump:!!:18779::::::
           
  1. awk進行運算
[[email protected] ~]# awk 'BEGIN{print 1+1}'
2
[[email protected] ~]# awk 'BEGIN{print 2^3}'
8
[[email protected] ~]# awk 'BEGIN{print 2/3}'
0.666667
[[email protected] ~]# awk 'BEGIN{x=2;x++;print x}'
3
           
  1. awk指定分隔符
[[email protected] ~]# awk 'BEGIN{FS=":"}{print $1}' pp.bak     
####  這裡的BEGIN表示開始,就是第一行與之前的開始,如果不加第一行就不會進行後面的指令序列,FS指定列的分隔符為冒号
root
bin
daemon
adm
lp
sync
[[email protected] ~]# awk 'END{print NR}' pp.bak   
####  END表示執行指令序列的最後一個,這裡表示從上往下顯示行号,最後一個是6
6
[[email protected] ~]# awk 'BEGIN{FS=":";OFS="----"}{print $1,$2}' pp.bak   //OFS指定列印的文本列之間的連接配接符
root----x
bin----x
daemon----x
adm----x
lp----x
sync----x
[[email protected] ~]# awk 'BEGIN{RS=":";ORS="----"}{print $2,$1,$0}' pp.bak 
####  RS表示分行符,這裡表示到冒号處就分行,ORS表示每行之間的連接配接符
 root root---- x x---- 0 0---- 0 0---- root root---- /root /root----bin /bin/bash /bin/bash
bin---- x x---- 1 1---- 1 1---- bin bin---- /bin /bin----daemon /sbin/nologin /sbin/nologin
daemon---- x x---- 2 2---- 2 2---- daemon daemon---- /sbin /sbin----adm /sbin/nologin /sbin/nologin
adm---- x x---- 3 3---- 4 4---- adm adm---- /var/adm /var/adm----lp /sbin/nologin /sbin/nologin
lp---- x x---- 4 4---- 7 7---- lp lp---- /var/spool/lpd /var/spool/lpd----sync /sbin/nologin /sbin/nologin
sync---- x x---- 5 5---- 0 0---- sync sync---- /sbin /sbin---- /bin/sync /bin/sync
           
[[email protected] ~]# awk 'NR<3 || NR>5{print NR,$0}' pp.bak        //列印行号小于3或大于5的行
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
[[email protected] ~]# awk 'NR>3 && NR<6{print NR,$0}' pp.bak         //列印行号大于3且小于6的行
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

           
  1. awk的if語句
單分支 :if(){}
雙分支 ;if(){}else{}
多分支 :if(){}else if(){}else{}
           
[[email protected] ~]# awk -F: '{if($3<4){print $0}}' pp.bak    //如果第三列的uid小如4就列印
root:x:0:0:root:/root:/bin/bash
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
[[email protected] ~]# awk -F: '{if($3<4){print $0}else{print $1}}' pp.bak    //在上面的基礎上uid不小于4時列印第一列
root:x:0:0:root:/root:/bin/bash
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
sync
           

繼續閱讀