标签(空格分隔): 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里最大的做用就是去重复。请同窗们仔细理解,多动手试验一下。