標籤(空格分隔): Linux實戰教學筆記-陳思齊html
要弄懂awk程序,必須熟悉瞭解這個工具的規則。本實戰筆記的目的是經過實際案例或面試題帶同窗們熟練掌握awk在企業中的用法,而不是awk程序的幫助手冊。mysql
awk不只僅時linux系統中的一個命令,並且是一種編程語言,能夠用來處理數據和生成報告(excel)。處理的數據能夠是一個或多個文件,能夠是來自標準輸入,也能夠經過管道獲取標準輸入,awk能夠在命令行上直接編輯命令進行操做,也能夠編寫成awk程序來進行更爲複雜的運用。本章主要講解awk命令的運用。linux
[root@chensiqi1 ~]# cat /etc/redhat-release CentOS release 6.8 (Final) [root@chensiqi1 ~]# uname -r 2.6.32-642.el6.x86_64 [root@chensiqi1 ~]# ll `which awk` lrwxrwxrwx. 1 root root 4 Dec 23 20:25 /bin/awk -> gawk [root@chensiqi1 ~]# awk --version GNU Awk 3.1.7 Copyright (C) 1989, 1991-2009 Free Software Foundation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.
awk處理的內容能夠來自標準輸入(<),一個或多個文本文件或管道。面試
示例1-1: 基本的模式和動做正則表達式
[root@chensiqi1 ~]# awk -F ":" 'NR>=2 && NR<=6{print NR,$1}' /etc/passwd 2 bin 3 daemon 4 adm 5 lp 6 sync 命令說明: -F 指定分隔符爲冒號,至關於以「:」爲菜刀,進行字段的切割。 NR>=2 && NR<=6:這部分表示模式,是一個條件,表示取第2行到第6行。 {print NR,$1}:這部分表示動做,表示要輸出NR行號和$1第一列。
示例1-2 只有模式redis
[root@chensiqi1 ~]# awk -F ":" 'NR>=2&&NR<=6' /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 sync:x:5:0:sync:/sbin:/bin/sync 命令說明: -F指定分隔符爲冒號 NR>=2&&NR<=6這部分是條件,表示取第2行到第6行。 可是這裏沒有動做,這裏你們須要瞭解若是隻有條件(模式)沒有動做,awk默認輸出整行
示例1-3:只有動做算法
[root@chensiqi1 ~]# awk -F ":" '{print NR,$1}' /etc/passwd 1 root 2 bin 3 daemon 4 adm 5 lp 6 sync 7 shutdown 8 halt 9 mail 10 uucp 如下省略.... 命令說明: -F指定分隔符爲冒號 這裏沒有條件,表示對每一行都處理 {print NR,$1}表示動做,顯示NR行號與$1第一列 這裏要理解沒有條件的時候,awk會處理每一行。
示例1-4:多個模式和動做sql
[root@chensiqi1 ~]# awk -F ":" 'NR==1{print NR,$1}NR==2{print NR,$NF}' /etc/passwd 1 root 2 /sbin/nologin 命令說明: -F指定分隔符爲冒號 這裏有多個條件與動做的組合 NR==1表示條件,行號(NR)等於1的條件知足的時候,執行{print NR,$1}動做,輸出行號與第一列。 NR==2表示條件,行號(NR)等於2的條件知足的時候,執行{print NR,$NF}動做,輸出行號與最後一列($NF)
注意:shell
在深刻了解awk前,咱們須要知道awk如何處理文件的。編程
示例1-5 示例文件的建立
[root@chensiqi1 ~]# mkdir /server/files/ -p [root@chensiqi1 ~]# head /etc/passwd > /server/files/awkfile.txt [root@chensiqi1 ~]# cat /server/files/awkfile.txt 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 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
這個文件僅包含十行文件,咱們使用下面的命令:
示例1-6 awk執行過程演示
[root@chensiqi1 ~]# awk 'NR>=2{print $0}' /server/files/awkfile.txt 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 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin 命令說明: 條件NR>=2,表示行號大於等於2時候,執行{print $0}顯示整行。 awk是經過一行一行的處理文件,這條命令中包含模式部分(條件)和動做部分(動做),awk將處理模式(條件)指定的行
1)awk讀入第一行內容
2)判斷是否符合模式中的條件NR>=2
a,若是匹配則執行對應的動做{print $0}
b,若是不匹配條件,繼續讀取下一行
3)繼續讀取下一行
4)重複過程1-3,直到讀取到最後一行(EOF:end of file)
接下來我給你們帶來兩個新概念記錄和字段,這裏爲了方便你們理解能夠把記錄就看成行即記錄==行,字段至關於列,字段==列。
名稱 | 含義 |
---|---|
record | 記錄,行 |
field | 域,區域,字段,列 |
查看一下下面這段文字
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 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
思考:
一共有多少行呢?你如何知道的?經過什麼標誌?
awk對每一個要處理的輸入數據認爲都是具備格式和結構的,而不只僅是一堆字符串。默認狀況下,每一行內容都是一條記錄,並以換行符分隔(\n)結束
awk使用內置變量RS來存放輸入記錄分隔符,RS表示的是輸入的記錄分隔符,這個值能夠經過BEGIN模塊從新定義修改。
示例1-1:使用「/」爲默認記錄分隔符
示例文件:
[root@chensiqi1 ~]# cat /server/files/awkfile.txt 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 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
[root@chensiqi1 ~]# awk 'BEGIN{RS="/"}{print NR,$0}' /server/files/awkfile.txt 1 root:x:0:0:root: 2 root: 3 bin 4 bash bin:x:1:1:bin: 5 bin: 6 sbin 7 nologin daemon:x:2:2:daemon: 8 sbin: 9 sbin 10 nologin adm:x:3:4:adm: 11 var 12 adm: 13 sbin 14 nologin lp:x:4:7:lp: 15 var 16 spool 17 lpd: 18 sbin 19 nologin sync:x:5:0:sync: 20 sbin: 21 bin 22 sync shutdown:x:6:0:shutdown: 23 sbin: 24 sbin 25 shutdown halt:x:7:0:halt: 26 sbin: 27 sbin 28 halt mail:x:8:12:mail: 29 var 30 spool 31 mail: 32 sbin 33 nologin uucp:x:10:14:uucp: 34 var 35 spool 36 uucp: 37 sbin 38 nologin 命令說明: 在每行的開始先打印輸出NR(記錄號行號),並打印出每一行$0(整行)的內容。 咱們設置RS(記錄分隔符)的值爲「/」,表示一行(記錄)以「/」結束 在awk眼中,文件是從頭至尾一段連續的字符串,恰巧中間有些\n(回車換行符),\n也是字符哦。
咱們回顧下「行(記錄)」究竟是什麼意思?
在工做中,咱們能夠經過修改RS變量的值來決定行的結束標誌,最終來決定「每行」的內容。
爲了方便人們理解,awk默認就把RS的值設置爲「\n」
注意:
awk的BEGIN模塊,我會在後面(模式-BEGIN模塊)詳細講解,此處你們僅須要知道在BEGIN模塊裏面咱們來定義一些awk內置變量便可。
示例1-2:NR記錄號
[root@chensiqi1 ~]# awk '{print NR,$0}' /server/files/awkfile.txt 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 7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown 8 halt:x:7:0:halt:/sbin:/sbin/halt 9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin 10 uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin 命令說明: NR既number of record,當前記錄的記錄號,剛開始學也能夠理解爲行號。 $0表示整行或者說整個記錄
注:(此處使用sort與uniq便可)
題目:
題目建立方法:
sed -r '1,10s#[^a-zA-Z]+# #g' /etc/passwd>/server/files/count.txt
[root@chensiqi1 files]# cat /server/files/count.txt root x root root bin bash bin x bin bin sbin nologin daemon x daemon sbin sbin nologin adm x adm var adm sbin nologin lp x lp var spool lpd sbin nologin sync x sync sbin bin sync shutdown x shutdown sbin sbin shutdown halt x halt sbin sbin halt mail x mail var spool mail sbin nologin uucp x uucp var spool uucp sbin nologin
思路:
讓全部單詞排成一列,這樣每一個單詞都是單獨的一行
1)設置RS值爲空格
2)將文件裏面的全部空格替換爲回車換行符「\n」
3)grep全部連續的字母,grep -o參數讓他們排成一列。
方法一:
[root@chensiqi1 files]# awk 'BEGIN{RS="[ ]+"}{print $0}' count.txt | sort |uniq -c|sort 1 1 bash 1 lpd 2 daemon 2 lp 3 adm 3 halt 3 mail 3 root 3 shutdown 3 spool 3 sync 3 uucp 4 var 5 bin 6 nologin 10 x 12 sbin
方法二:
[root@chensiqi1 files]# cat count.txt | tr " " "\n" | sort | uniq -c | sort 1 bash 1 lpd 2 daemon 2 lp 3 adm 3 halt 3 mail 3 root 3 shutdown 3 spool 3 sync 3 uucp 4 var 5 bin 6 nologin 10 x 12 sbin
方法三:
[root@chensiqi1 files]# grep -o "[a-zA-Z]\+" count.txt | sort | uniq -c | sort 1 bash 1 lpd 2 daemon 2 lp 3 adm 3 halt 3 mail 3 root 3 shutdown 3 spool 3 sync 3 uucp 4 var 5 bin 6 nologin 10 x 12 sbin
awk學習技巧一則:
大象放冰箱分幾步?打開冰箱,把大象放進去,關閉冰箱門。
awk也是同樣的,一步一步來,先修改了RS,而後用NR調試,看看到底如何分隔的。而後經過sort排序,uniq -c去重
OFS輸出字段(列)分隔符
- awk使用內置變量FS來記錄區域分隔符的內容,FS能夠在命令行上經過-F參數來更改,也能夠經過BEGIN模塊來更改。
- 而後經過$n,n是整數,來取被切割後的區域,$1取第一個區域,$2取第二個區域,$NF取最後一個區域。
下面咱們經過示例來增強學習。
示例1-3:指定分隔符
[root@chensiqi1 files]# awk -F ":" 'NR>=2&&NR<=5{print $1,$3}' /server/files/awkfile.txt bin 1 daemon 2 adm 3 lp 4 命令說明: 以:(冒號)爲分隔符,顯示第2行到第5行之間的第一區域和第三區域。
企業面試題:同時取出chensiqi和215379068這兩個內容(指定多分隔符)
[root@chensiqi1 files]# echo "I am chensiqi,my qq is 1234567890">>/server/files/chensiqi.txt [root@chensiqi1 files]# cat /server/files/chensiqi.txt I am chensiqi,my qq is 1234567890
同時取出chensiqi和1234567890這兩個內容。
思路:
咱們用默認的想法一次使用一把刀,須要配合管道的。如何同時使用兩把刀呢?看下面的結果
[root@chensiqi1 files]# awk -F "[ ,]" '{print $3,$NF}' /server/files/chensiqi.txt chensiqi 1234567890 命令說明: 經過命令-F參數指定區域分隔符 [ ,]是正則表達式裏面的內容,它表示一個總體,「一個」字符,既空格或者逗號(,),合併在一塊兒,-F 「[ ,]」就表示以空格或者逗號(,)爲區域分隔符
小技巧:
在動做(‘{print $3,$NF}’)裏面的逗號,表示空格,其實動做中的逗號就是OFS的值,咱們會在後面說明。剛開始你們把動做中的都逗號,看成空格便可。
示例:默認分隔符和指定分隔符會有些差別
[root@chensiqi1 files]# ifconfig eth0 | awk 'NR==2' >/server/files/awkblank.txt [root@chensiqi1 files]# cat /server/files/awkblank.txt inet addr:192.168.197.133 Bcast:192.168.197.255 Mask:255.255.255.0 #默認分隔符時候 [root@chensiqi1 files]# awk '{print $1}' /server/files/awkblank.txt inet #指定分隔符時候 [root@chensiqi1 files]# awk -F "[ :]+" '{print $1}' /server/files/awkblank.txt [root@chensiqi1 files]# awk -F "[ :]+" '{print $2}' /server/files/awkblank.txt inet 命令說明: awk默認的FS分隔符對於空格序列,一個空格或多個空格tab都認爲是同樣的,一個總體。
如今說說ORS和OFS這兩個內置變量的含義。
如今你應該會對awk的記錄字段有所瞭解了,下面咱們總結一下,學會給階段性知識總結是學好運維的必備技能。
$符號表示取某個列(字段),$1$2$NF
$NF
取最後一個列(區域。)到了這裏咱們回頭看看,咱們以前學習的內容。
比較核心經常使用的是字段。
另外這些企業面試題但是學會awk的必備,必須本身也能寫出來。
接下來就詳細介紹下,awk的模式都有幾種:
awk的模式是你玩好awk的必備也是最基礎的內容,必須熟練掌握
awk同sed同樣也能夠經過模式匹配來對輸入的文本進行匹配處理。說到模式匹配,確定少不了正則表達式,awk也支持大量的正則表達式模式,大部分與sed支持的元字符相似,並且正則表達式是玩轉三劍客的必備工具,下表列出了awk支持的正則表達式元字符:
awk默認就支持的元字符:
元字符 | 功能 | 示例 | 解釋 |
---|---|---|---|
^ | 字符串開頭 | /^chensiqi/或$3~/^chensiqi/ | 匹配全部以chensiqi開頭的字符串;匹配出全部第三列中以chensiqi開頭的 |
$ | 字符串結尾 | /chensiqi$/或$3~/chensiqi$/ | 匹配全部以chensiqi結尾的字符串;匹配第三列中以chensiqi結尾的 |
.(點) | 匹配任意但個字符(包括回車符) | /c..l/ | 匹配字母c,而後兩個任意字符,再以l結尾的行 |
* | 重複0個或多個前一個字符 | /a*cool/ | 匹配0個或多個a以後緊跟着cool的行 |
+ | 重複前一個字符一次或屢次 | /a+b/ | 匹配一個或多個a加上字符串b的行 |
? | 匹配0個或一個前邊的字符 | /a?b/ | 匹配以字母a或b或c開頭的行 |
[] | 匹配指定字符組內的任一個字符 | /^[abc]/ | 匹配以字母a或b或c開頭的行 |
[^] | 匹配不在指定字符組內的任一字符 | /^[^abc]/ | 匹配不以字母a或b或c開頭的行 |
() | 子表達式組合 | /(chensiqi)+/ | 表示一個或多個cool組合,當有一些字符須要組合時,使用括號括起來 |
| |
或者的意思 | /(chensiqi)|B/ |
匹配chensiqi或字母B的行 |
awk默認不支持的元字符:(參數--posix)
元字符 | 功能 | 示例 | 解釋 |
---|---|---|---|
x{m} | x字符重複m次 | /cool{5}/ | 匹配l字符5次 |
x{m,} | x字符重複至少m次 | /(cool){2,}/ | 匹配cool總體,至少2次 |
x{m,n} | x字符重複至少m次,但不超過n次 | /(cool){5,6}/ | 匹配cool總體,至少5次,最多6次 |
提示:
awk正則匹配操做符:
|~|用於對記錄或區域的表達式進行匹配|
|--|--|
|!~|用於表達與~相反的意思|
下面仍是經過具體示例來看看,awk如何來經過正則表達式匹配字符串的
[root@chensiqi1 files]# awk -F ":" '/^root/' awkfile.txt root:x:0:0:root:/root:/bin/bash
和下面的效果是同樣的
[root@chensiqi1 files]# awk -F ":" '$0~/^root/' awkfile.txt root:x:0:0:root:/root:/bin/bash
提示:
awk只用正則表達式的時候是默認匹配整行的即‘$0~/^root/’和‘/^root/’是同樣的。
[root@chensiqi1 files]# awk -F ":" '$5~/shutdown/' awkfile.txt shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
提示:
合併在一塊兒
$5~/shutdown/表示第五個區域(列)匹配正則表達式/shutdown/,既第5列包含shutdown這個字符串,則顯示這一行。
知道了如何使用正則表達式匹配操做符以後,咱們來看看awk正則與grep和sed不一樣的地方。
awk正則表達式
|^|匹配一個字符串的開頭|
|--|--|
|$|匹配一個字符串的結尾|
在sed和grep這兩個命令中,咱們都把它們看成行的開頭和結尾。可是在awk中他表示的是字符串的開頭和結尾。
接下來咱們經過練習題來聯繫awk如何使用正則表達式。
[root@chensiqi1 ~]# cat >>/server/files/reg.txt<<KOF Zhang Dandan 41117397 :250:100:175 Zhang Xiaoyu 390320151 :155:90:201 Meng Feixue 80042789 :250:60:50 Wu Waiwai 70271111 :250:80:75 Liu Bingbing 41117483 :250:100:175 Wang Xiaoai 3515064655 :50:95:135 Zi Gege 1986787350 :250:168:200 Li Youjiu 918391635 :175:75:300 Lao Nanhai 918391635 :250:100:175 KOF
Zhang Dandan 41117397 :250:100:175 Zhang Xiaoyu 390320151 :155:90:201 Meng Feixue 80042789 :250:60:50 Wu Waiwai 70271111 :250:80:75 Liu Bingbing 41117483 :250:100:175 Wang Xiaoai 3515064655 :50:95:135 Zi Gege 1986787350 :250:168:200 Li Youjiu 918391635 :175:75:300 Lao Nanhai 918391635 :250:100:175
說明:
練習題1:顯示姓Zhang的人的第二次捐款金額及她的名字
練習題2:顯示Xiaoyu的名字和ID號碼
練習題3:顯示全部以41開頭的ID號碼的人的全名和ID號碼
練習題4:顯示全部以一個D或X開頭的人名全名
練習題5:顯示全部ID號碼最後一位數字是1或5的人的全名
練習題6:顯示Xiaoyu的捐款,每一個值都有以$開頭。如$520$200$135
練習題7:顯示全部人的全名,以姓,名的格式顯示,如Meng,Feixue
示例1:顯示姓Zhang的人的第二次捐款金額及她的名字
[root@chensiqi1 files]# cat reg.txt Zhang Dandan 41117397 :250:100:175 Zhang Xiaoyu 390320151 :155:90:201 Meng Feixue 80042789 :250:60:50 Wu Waiwai 70271111 :250:80:75 Liu Bingbing 41117483 :250:100:175 Wang Xiaoai 3515064655 :50:95:135 Zi Gege 1986787350 :250:168:200 Li Youjiu 918391635 :175:75:300 Lao Nanhai 918391635 :250:100:175 [root@chensiqi1 files]# awk -F "[ :]+" '$1~/^Zhang/{print $2,$(NF-1)}' reg.txt Zhang 100 Zhang 90
說明:
注意:
NF是一行中有多少列,NF-1整行就是倒數第二列。
$(NF-1)就是取倒數第二列內容。
示例2:顯示Xiaoyu的姓氏和ID號碼
[root@chensiqi1 files]#cat reg.txt Zhang Dandan 41117397 :250:100:175 Zhang Xiaoyu 390320151 :155:90:201 Meng Feixue 80042789 :250:60:50 Wu Waiwai 70271111 :250:80:75 Liu Bingbing 41117483 :250:100:175 Wang Xiaoai 3515064655 :50:95:135 Zi Gege 1986787350 :250:168:200 Li Youjiu 918391635 :175:75:300 Lao Nanhai 918391635 :250:100:175 [root@chensiqi1 files]# awk -F "[ :]+" '$2~/^Xiaoyu/{print $1,$3}' reg.txt Zhang 390320151 命令說明: 指定分隔符-F 「【:】+」 $2~/Xiaoyu/表示條件,第二列包含Xiaoyu時候執行對應的動做 {print $1,$3}表示動做,顯示第一列和第三列的內容
示例3:顯示全部以41開頭的ID號碼的人的全名和ID號碼
[root@chensiqi1 files]# cat reg.txt Zhang Dandan 41117397 :250:100:175 Zhang Xiaoyu 390320151 :155:90:201 Meng Feixue 80042789 :250:60:50 Wu Waiwai 70271111 :250:80:75 Liu Bingbing 41117483 :250:100:175 Wang Xiaoai 3515064655 :50:95:135 Zi Gege 1986787350 :250:168:200 Li Youjiu 918391635 :175:75:300 Lao Nanhai 918391635 :250:100:175 [root@chensiqi1 files]# awk -F "[ :]+" '$3~/^(41)/{print $1,$2,$3}' reg.txt Zhang Dandan 41117397 Liu Bingbing 41117483
示例4:顯示全部以一個D或X開頭的人名全名
[root@chensiqi1 files]# cat reg.txt Zhang Dandan 41117397 :250:100:175 Zhang Xiaoyu 390320151 :155:90:201 Meng Feixue 80042789 :250:60:50 Wu Waiwai 70271111 :250:80:75 Liu Bingbing 41117483 :250:100:175 Wang Xiaoai 3515064655 :50:95:135 Zi Gege 1986787350 :250:168:200 Li Youjiu 918391635 :175:75:300 Lao Nanhai 918391635 :250:100:175 [root@chensiqi1 files]# awk -F "[ :]+" '$2~/^D|^X/{print $1,$2}' reg.txt Zhang Dandan Zhang Xiaoyu Wang Xiaoai 命令說明: -F 「【 :】+」指定分隔符 |表示或,^以...開頭
注意:
這裏要用()括號表示即^(D|X)至關於^D|^X,有的同窗寫成^D|X這樣是錯誤的。
示例5:顯示全部ID號碼最後一位數字是1或5的人的全名
[root@chensiqi1 files]# cat reg.txt Zhang Dandan 41117397 :250:100:175 Zhang Xiaoyu 390320151 :155:90:201 Meng Feixue 80042789 :250:60:50 Wu Waiwai 70271111 :250:80:75 Liu Bingbing 41117483 :250:100:175 Wang Xiaoai 3515064655 :50:95:135 Zi Gege 1986787350 :250:168:200 Li Youjiu 918391635 :175:75:300 Lao Nanhai 918391635 :250:100:175 [root@chensiqi1 files]# awk -F "[ :]+" '$3~/1$|5$/{print $1,$2}' reg.txt Zhang Xiaoyu Wu Waiwai Wang Xiaoai Li Youjiu Lao Nanhai
示例6:顯示Xiaoyu的捐款,每一個值都有以$開頭。如$520$200$135
[root@chensiqi1 files]# cat reg.txt Zhang Dandan 41117397 :250:100:175 Zhang Xiaoyu 390320151 :155:90:201 Meng Feixue 80042789 :250:60:50 Wu Waiwai 70271111 :250:80:75 Liu Bingbing 41117483 :250:100:175 Wang Xiaoai 3515064655 :50:95:135 Zi Gege 1986787350 :250:168:200 Li Youjiu 918391635 :175:75:300 Lao Nanhai 918391635 :250:100:175 [root@chensiqi1 files]# awk -F "[ :]+" '$2~/Xiaoyu/{print "$"$4"$"$5"$"$6}' reg.txt $155$90$201
示例7:顯示全部人的全名,以姓,名的格式顯示,如Meng,Feixue
[root@chensiqi1 files]# cat reg.txt Zhang Dandan 41117397 :250:100:175 Zhang Xiaoyu 390320151 :155:90:201 Meng Feixue 80042789 :250:60:50 Wu Waiwai 70271111 :250:80:75 Liu Bingbing 41117483 :250:100:175 Wang Xiaoai 3515064655 :50:95:135 Zi Gege 1986787350 :250:168:200 Li Youjiu 918391635 :175:75:300 Lao Nanhai 918391635 :250:100:175 [root@chensiqi1 files]# awk -F "[ ]+" '{print $1","$2}' reg.txt Zhang,Dandan Zhang,Xiaoyu Meng,Feixue Wu,Waiwai Liu,Bingbing Wang,Xiaoai Zi,Gege Li,Youjiu Lao,Nanhai
最簡單:hostname -I
awk處理:
方法一:
[root@chensiqi1 files]# ifconfig eth0|awk 'BEGIN{RS="[ :]"}NR==31' 192.168.197.133
方法二:
[root@chensiqi1 files]# ifconfig eth0 | awk -F "(addr:)|( Bcast:)" 'NR==2{print $2}' 192.168.197.133
方法三:
[root@chensiqi1 files]# ifconfig eth0 | awk -F "[ :]+" 'NR==2{print $4}' 192.168.197.133
方法四:
[root@chensiqi1 files]# ifconfig eth0 | awk -F "[^0-9.]+" 'NR==2{print $2}' 192.168.197.133
提示:
注意:
正則表達式是玩好awk的必要條件,必會掌握
[root@chensiqi1 files]# echo "------======1########2" ------======1########2 [root@chensiqi1 files]# echo "------======1########2" | grep "[-=#]" ------======1########2 [root@chensiqi1 files]# echo "------======1########2" | grep -o "[-=#]" - - - - - - = = = = = = # # # # # # # #
awk中的花括號有些不經常使用,可是偶爾會用到這裏簡單介紹。
示例:取出awkfile中第一列包含一個o或者兩個o的行
[root@chensiqi1 files]# awk -F: '$1~/o{1,2}/' awkfile.txt [root@chensiqi1 files]# awk -F: --posix '$1~/o{1,2}/' awkfile.txt root:x:0:0:root:/root:/bin/bash daemon:x:2:2:daemon:/sbin:/sbin/nologin shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown [root@chensiqi1 files]# awk -F: --re-interval '$1~/o{1,2}/' awkfile.txt root:x:0:0:root:/root:/bin/bash daemon:x:2:2:daemon:/sbin:/sbin/nologin shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
思路:
linux下面服務與端口信息的對應表格在/etc/services裏面,因此這道題要處理/etc/services文件。
咱們簡單分析如下servics文件:
[root@chensiqi1 ~]# sed -n '23,30p' /etc/services tcpmux 1/tcp # TCP port service multiplexer tcpmux 1/udp # TCP port service multiplexer rje 5/tcp # Remote Job Entry rje 5/udp # Remote Job Entry echo 7/tcp echo 7/udp discard 9/tcp sink null discard 9/udp sink null
從23行開始基本上每一行第一列是服務名稱,第二列的第一部分是端口號,第二列的第二部分是tcp或udp協議。
方法:
[root@chensiqi1 ~]# awk -F "[ /]+" '$1~/^(ssh)$|^(http)$|^(https)$|^(mysql)$|^(ftp)$/{print $1,$2}' /etc/services |sort|uniq ftp 21 http 80 https 443 mysql 3306 ssh 22
提示:
同窗們本身嘗試下
以前咱們看了正則表達式在awk下的運用,下面再具體看看比較表達式如何在awk下工做。
awk是一種編程語言,可以進行更爲複雜的判斷,當條件爲真時候,awk就執行相關的action。主要是針對某一區域作出相關的判斷,好比打印成績在80分以上的行,這樣就必須對這一區域作比較判斷,下表列出了awk可使用的關係運算符,能夠用來比較數字字符串,還有正則表達式。當表達式爲真時候,表達式結果1,否0,只有表達式爲真,awk才執行相關的action
運算符 | 含義 | 示例 |
---|---|---|
< | 小於 | x>y |
<= | 小於等於 | x<=y |
== | 等於 | x==y |
!= | 不等於 | x!=y |
>= | 大於或等於 | x>=y |
> | 大於 | x<y |
以上運算符是針對數字的,下面兩個運算符以前已有示例,針對字符串
~ | 與正則表達式匹配 | x~/y/ |
---|---|---|
!~ | 與正則表達式不匹配 | x!~y |
思路:
想表示一個範圍,一個行的範圍,就要用到NR這個內置變量了,同時也要用到比較表達式。
答案:
[root@www ~]# awk 'NR>=23&&NR<=30' /etc/services [root@www ~]# awk 'NR>22&&NR<31' /etc/services
過程:
[root@www ~]# awk 'NR>=23&&NR<=30' /etc/services tcpmux 1/tcp # TCP port service multiplexer tcpmux 1/udp # TCP port service multiplexer rje 5/tcp # Remote Job Entry rje 5/udp # Remote Job Entry echo 7/tcp echo 7/udp discard 9/tcp sink null discard 9/udp sink null [root@www ~]# awk 'NR>22&&NR<31' /etc/services tcpmux 1/tcp # TCP port service multiplexer tcpmux 1/udp # TCP port service multiplexer rje 5/tcp # Remote Job Entry rje 5/udp # Remote Job Entry echo 7/tcp echo 7/udp discard 9/tcp sink null discard 9/udp sink null
說明:
1)比較表達式比較經常使用的仍是表示大於等於,小於等於或者等於,根據這個例子來學習便可
2)NR表示行號,大於等於23即,NR>=23小於等於30,即NR<=30
3)合起來就是NR>=23而且NR<=30,&&表示而且,同時成立的意思。
4)換一種表達式方法就是大於22行小於31行,即NR>22&&NR<31
示例:找出/etc/passwd中第五列是root的行
測試文件:
[root@www ~]# cat /server/files/awk_equal.txt root:x:0:0:root:/root:/bin/bash root:x:0:0:rootroot:/root:/bin/bash root:x:0:0:rootrooot:/root:/bin/bash root:x:0:0:rootrooot:/root:/bin/bash root:x:0:0:/root:/bin/bash
答案:
awk -F":" '$5=="root"' /server/files/awk_equal.txt awk -F":" '$5~/^root$/' /server/files/awk_equal.txt
過程:
#方法一: [root@www ~]# awk -F":" '$5=="root"' /server/files/awk_equal.txt root:x:0:0:root:/root:/bin/bash #方法二: [root@www ~]# awk -F":" '$5~/^root$/' /server/files/awk_equal.txt root:x:0:0:root:/root:/bin/bash
咱們若是想要徹底匹配root這個字符串,那就用$5=="root"
便可,這也是答案裏面給你們的。
方法二:
此題也可經過正則匹配來限制root的字符串。$5~/^root$/
pattern1 | pattern2 | |
---|---|---|
從哪裏來 | 到 | 哪裏去 |
條件1 | 條件2 |
1)還記得sed使用地址範圍來處理文本內容嘛?awk的範圍模式,與sed相似,可是又有不一樣,awk不能直接使用行號來做爲範圍起始地址,由於awk具備內置變量NR來存儲記錄號,全部須要使用NR=1,NR=5這樣來使用。
2)範圍模式處理的原則是:先匹配從第一個模式的首次出現到第二個模式的首次出現之間的內容,執行action。而後匹配從第一個模式的下一次出現到第二個模式的下一次出現,直到文本結束。若是匹配到第一個模式而沒有匹配到第二個模式,則awk處理從第一個模式開始直到文本結束所有的行。若是第一個模式不匹配,就算第二個模式匹配,awk依舊不處理任何行。
awk '/start pos/,/end pos/{print $)} passwd chensiqi' awk '/start pos/,NR==XXX{print $0}' passwd chensiqi
範圍模式的時候,範圍條件的時候,表達式必須能匹配一行。
示例1:
[root@www files]# awk 'NR==2,NR==5{print NR,$0}' count.txt 2 bin x bin bin sbin nologin 3 daemon x daemon sbin sbin nologin 4 adm x adm var adm sbin nologin 5 lp x lp var spool lpd sbin nologin
說明:
條件是:從第二行,到第五行
動做是:顯示行號(NR)和整行($0)
合起來就是顯示第二行到第五行的行好和整行的內容
示例2:
[root@www files]# awk '/^bin/,NR==5{print NR,$0}' awkfile.txt 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
說明:
條件是:從以bin開頭的行,到第五行
動做是:顯示行號和整行內容
合起來就是顯示從以bin開頭的行,到第五行中的行號和整行內容。
示例3:
[root@www files]# awk -F":" '$5~/^bin/,/^lp/{print NR,$0}' awkfile.txt 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
說明:
條件:從第五列以bin開頭的行到以lp開頭的行
動做:顯示行號和正航內容
合起來:從第三列以bin開始的行到以lp開頭的行並顯示其行號和整行內容
[root@www files]# awk -F: '$5~/^bin/,$5~/^lp/{print NR,$0}' awkfile.txt 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
說明:
條件:從第三列以bin開頭字符串的行到第三列以lp開頭字符串的行
動做:顯示行號和整行
1)第一個做用,內置變量的定義
示例:取eth0的IP地址
答案:
[root@www files]# ifconfig eth0|awk -F "(addr:)|( Bcast:)" 'NR==2{print $2}' 192.168.197.133 [root@www files]# ifconfig eth0 | awk -F "[ :]+" 'NR==2{print $4}' 192.168.197.133 [root@www files]# ifconfig eth0 | awk -F "[^0-9.]+" 'NR==2{print $2}' 192.168.197.133 #上面的也能夠寫成 [root@www files]# ifconfig eth0 | awk 'BEGIN{FS="(addr:)|( Bcast:)"} NR==2{print $2}' 192.168.197.133 [root@www files]# ifconfig eth0 | awk 'BEGIN{FS="[ :]+"}NR==2{print $4}' 192.168.197.133 [root@www files]# ifconfig eth0 | awk 'BEGIN{FS="[^0-9.]+"}NR==2{print $2}' 192.168.197.133
注意:
命令行-F本質就是修改的FS變量
2)第二個做用,在讀取文件以前,輸出些提示性信息(表頭)。
[root@www files]# awk -F: 'BEGIN{print "username","UID"}{print $1,$3}' awkfile.txt username UID #這就是輸出的表頭信息 root 0 bin 1 daemon 2 adm 3 lp 4 sync 5 shutdown 6 halt 7 mail 8 uucp 10
說明:
要在第一行輸出一些username和UID,咱們應該想到BEGIN{}這個特殊的條件(模式),由於BEGIN{}在awk讀取文件以前執行的。
因此結果是BEGIN{print "username","UID"}
,注意print命令裏面雙引號吃啥吐啥,原樣輸出。
而後咱們實現了在輸出文件內容以前輸出「username」和「UID」,下一步輸出文件的第一列和第三列即{print $1,$3}
最後結果就是BEGIN{print "username","UID"}{print $1,$3}
3)第三個做用,使用BEGIN模塊的特殊性質,進行一些測試。
[root@www files]#簡單輸出內容: [root@www files]# awk 'BEGIN{print "hello world!"}' hello world! [root@www files]# #進行計算 [root@www files]# awk 'BEGIN{print 10/3}' 3.33333 [root@www files]# awk 'BEGIN{print 10/3+1}' 4.33333 [root@www files]# awk 'BEGIN{print 10/3+1/4*9}' 5.58333 [root@www files]# #和變量有關的操做 [root@www files]# awk 'BEGIN{a=1;b=2;print a,b}' 1 2 [root@www files]# awk 'BEGIN{a=1;b=2;print a,b,a+b}' 1 2 3
4)第四種用法:配合getline讀取文件,後面awk函數處講解
[root@chensiqi files]# awk 'BEGIN{a=abcd;print a}' [root@chensiqi files]# awk 'BEGIN{abcd=123456;a=abcd;print a}' 123456 [root@chensiqi files]# awk 'BEGIN{a="abcd";print a}' abcd
說明:
沒有文件awk依舊能夠處理BEGIN模式下的動做(命令)
EHD在awk讀取完全部的文件的時候,再執行END模塊,通常用來輸出一個結果(累加,數組結果),也能夠是和BEGIN模塊相似的結尾標識信息
[root@chensiqi files]# awk 'BEGIN{print "hello world!"}{print NR,$0}END{print "end of file"}' count.txt hello world! 1 root x root root bin bash 2 bin x bin bin sbin nologin 3 daemon x daemon sbin sbin nologin 4 adm x adm var adm sbin nologin 5 lp x lp var spool lpd sbin nologin 6 sync x sync sbin bin sync 7 shutdown x shutdown sbin sbin shutdown 8 halt x halt sbin sbin halt 9 mail x mail var spool mail sbin nologin 10 uucp x uucp var spool uucp sbin nologin end of file
與BEGIN模式相對應的END模式,格式同樣,可是END模式僅在awk處理完全部輸入行後才進行處理。
企業案例:統計/etc/servies文件裏的空行數量
思路:
a)空行經過正則表達式來實現:^$
b)統計數量:
方法一:grep
[root@chensiqi files]# grep "^$" /etc/services | wc -l 16 [root@chensiqi files]# grep -c "^$" /etc/services 16 說明: grep命令-c表示count計數統計包含^$的行一共有多少。
方法二:
[root@chensiqi files]# awk '/^$/{i++}END{print i}' /etc/services 16
提示:
使用了awk的技術功能,很經常使用
第一步:統計空行個數
/^$/
表示條件,匹配出空行,而後執行{i++}(i++等於i=i+1)即:/^$/{i=i+1}
咱們能夠經過/^$/{i=i+1;print i}
來查看awk執行過程
[root@chensiqi files]# awk '/^$/{i=i+1;print "the value of i is:"i}' /etc/services the value of i is:1 the value of i is:2 the value of i is:3 the value of i is:4 the value of i is:5 the value of i is:6 the value of i is:7 the value of i is:8 the value of i is:9 the value of i is:10 the value of i is:11 the value of i is:12 the value of i is:13 the value of i is:14 the value of i is:15 the value of i is:16
第二步:輸出最後結果
因此最終結果就是awk '/^$/{i=i+1}END{print "blank lines count:"i}' /etc/services
awk編程思想:
{print NR,$0}body
模塊處理,處理完畢後END{print "end of file"}
輸出一個結果企業面試題5:文件count.txt,文件內容是1到100(由seq 100生成),請計算文件每行值加起來的結果(計算1+...+100)
思路:
文件每一行都有且只有一個數字,因此咱們要讓文件的每行內容相加。
回顧一下上一道題咱們用的是i++即i=i+1
這裏咱們須要使用到第二個經常使用的表達式
i=i+$0
對比一下,其實只是把上邊的1換成了$0
[root@chensiqi files]# awk '{i=i+$0}END{print i}' count.txt 5050
在一個模式-動做語句中,模式決定動做何時執行,有時候動做會很是簡單:一條單獨的打印或賦值語句。在有些時候,動做有多是多條語句,語句之間用換行符或分號分開。
awk的動做中若是有兩個或兩個以上的語句,須要用分號分隔
動做部分你們理解爲花括號裏面的內容便可,整體分爲:
回顧一下awk的結構
awk -F 指定分隔符 ‘BRGIN{}END{}’,以下圖
#awk完整執行過程 [root@chensiqi ~]# awk -F ":" 'BEGIN{RS="/";print "hello world!"}{print NR,$0}END{print "end of file"}' /server/files/awkfile.txt hello world! 1 root:x:0:0:root: 2 root: 3 bin 4 bash bin:x:1:1:bin: 5 bin: 6 sbin 7 nologin daemon:x:2:2:daemon: 8 sbin: 9 sbin 10 nologin adm:x:3:4:adm: 11 var 12 adm: 13 sbin 14 nologin lp:x:4:7:lp: 15 var 16 spool 17 lpd: 18 sbin 19 nologin sync:x:5:0:sync: 20 sbin: 21 bin 22 sync shutdown:x:6:0:shutdown: 23 sbin: 24 sbin 25 shutdown halt:x:7:0:halt: 26 sbin: 27 sbin 28 halt mail:x:8:12:mail: 29 var 30 spool 31 mail: 32 sbin 33 nologin uucp:x:10:14:uucp: 34 var 35 spool 36 uucp: 37 sbin 38 nologin end of file
說明:
咱們·同時再命令行定義了分隔符和在BEGIN模式中定義了RS內置變量,在最後經過END模式輸出告終果
awk提供了數組來存放一組相關的值。
awk是一種編程語言,確定也支持數組的運用,可是又不一樣於c語言的數組。數組在awk中被稱爲關聯數組,由於它的下標既能夠是數字也能夠是字符串。下標一般被稱做key,而且與對應的數組元素的值關聯。數組元素的key和值都存儲在awk程序內部的一張表中,經過必定散列算法來存儲,因此數組元素都不是按順序存儲的。打印出來的順序也確定不是按照必定的順序,可是咱們能夠經過管道來對所需的數據再次操做來達到本身的效果。
如圖不難發現,awk數組就和酒店同樣。數組的名稱就像是酒店名稱,數組元素名稱就像酒店房間號碼,每一個數組元素裏面的內容就像是酒店房間裏面的人。
假設咱們有一個酒店
酒店<===>chensiqihotel
酒店裏面有幾個房間110,119,120,114這幾個房間
酒店110房間<===>chensiqihotel[110] 酒店120房間<===>chensiqihotel[120] 酒店119房間<===>chensiqihotel[119] 酒店114房間<===>chensiqihotel[114]
酒店房間裏面入住客人
酒店110房間住着xiaoyu<===>chensiqihotel[110]="xiaoyu" 酒店119房間住着ruxue<===>chensiqihotel[119]="ruxue" 酒店120房間住着dandan<===>chensiqihotel[120]="dandan" 酒店114房間住着waiwai<===>chensiqihotel[114]="waiwai"
示例:
[root@chensiqi ~]# awk 'BEGIN{chensiqihotel[110]="xiaoyu";chensiqihotel[119]="ruxue";chensiqihotel[120]="dandan";chensiqihotel[114]="waiwai";print chensiqihotel[110],chensiqihotel[119],chensiqihotel[120],chensiqihotel[114]}' xiaoyu ruxue dandan waiwai
[root@chensiqi ~]# awk 'BEGIN{chensiqihotel[110]="xiaoyu";chensiqihotel[119]="ruxue";chensiqihotel[120]="dandan";chensiqihotel[114]="waiwai";for(hotel in chensiqihotel)print hotel,chensiqihotel[hotel]}' 110 xiaoyu 120 dandan 114 waiwai 119 ruxue
企業面試題1:統計域名訪問次數
處理如下文件內容,將域名取出並根據域名進行計數排序處理:(百度和sohu面試題)
http://www.etiantian.org/index.html http://www.etiantian.org/1.html http://post.etiantian.org/index.html http://mp3.etiantian.org/index.html http://www.etiantian.org/3.html http://post.etiantian.org/2.html
思路:
1)以斜線爲菜刀取出第二列(域名)
2)建立一個數組
3)把第二列(域名)做爲數組的下標
4)經過相似於i++的形式進行計數
5)統計後把結果輸出
過程演示:
第一步:查看一下內容
[root@chensiqi ~]# awk -F "[/]+" '{print $2}' file www.etiantian.org www.etiantian.org post.etiantian.org mp3.etiantian.org www.etiantian.org post.etiantian.org 命令說明: 這是咱們須要計數的內容
第二步:計數
[root@chensiqi ~]# awk -F "[/]+" '{i++;print $2,i}' file www.etiantian.org 1 www.etiantian.org 2 post.etiantian.org 3 mp3.etiantian.org 4 www.etiantian.org 5 post.etiantian.org 6 命令說明: i++:i最開始是空的,當awk讀取一行,i自身+1
第三步:用數組替換i
[root@chensiqi ~]# awk -F "[/]+" '{h[$2]++;print $2,h["www.etiantian.org"]}' file www.etiantian.org 1 www.etiantian.org 2 post.etiantian.org 2 mp3.etiantian.org 2 www.etiantian.org 3 post.etiantian.org 3 命令說明: 1)將i替換成h[$2];至關於我建立了一個數組h[],而後用$2做爲個人房間號。可是目前房間裏是沒有東西的。也就是說h[$2]=h["www.etiantian.org"] and h["post.etiantian.org"] and h["mp3.etiantian.org"] 可是具體房間裏是沒有東西的也就是空。 2)h[$2]++就等於i++:也就是說我開始給房間里加東西;當出現一樣的東西,我就++ 3)print h["www.etiantian.org"]:意思就是說我開始要輸出了。我要輸出的是房間號爲「www.etiantian.org」裏面的內容。這裏面的內容最先是空的,隨着awk讀取每一行一旦出現房間號爲「www.etiantian.org」的房間時,我就給房間裏的內容進行++。 4)綜上,輸出的結果中,每次出現www.etiantian.org時,h["www.etiantian.org"]就會++。所以最後的輸出數字是3
第四步:輸出最終計數結果
[root@chensiqi ~]# awk -F "[/]+" '{h[$2]++}END{for(i in h)print i,h[i]}' file mp3.etiantian.org 1 post.etiantian.org 2 www.etiantian.org 3 [root@chensiqi ~]# 命令說明: 咱們最終須要輸出的是去重複之後的統計結果,因此得在END模塊裏進行輸出 for(i in h)遍歷這個數組,i裏存的都是房間號 print i,h[i]:輸出每個房間號及其房間裏的內容(計數結果)
提示: awk的應用裏最重要的一個功能就是計數,而數組在awk裏最大的做用就是去重複。請同窗們仔細理解,多動手試驗一下。