以前我介绍过sed,cut,tr,grep等等的命令来对文本进行处理,可是有时候发现这些命令并不能彻底的知足咱们的需求,直到我学习了awk,感受之前有些比较繁琐的命令能够根据awk轻易解决,这些命令的结合会给咱们处理文本带来巨大的便利。shell
1、awk简介express
awk其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。实际上 AWK 的确拥有本身的语言: AWK 程序设计语言 , 三位建立者已将它正式定义为“样式扫描和处理语言”。它容许您建立简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其余的功能。vim
awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤其强大。简单来讲awk就是把文件逐行的读入,以分隔符将每行切片,切开的部分再进行各类分析处理。centos
awk有3个不一样版本: awk、nawk和gawk,未做特别说明,通常指gawk,gawk 是 AWK 的 GNU 版本。
数组
awk程序的报告生成能力通常用来从大文本文件里提取数据元素并将它们格式化成可读的报告。最完美的样例是格式化日志文件 bash
2、awk用法
app
awk 'BEGIN{ commands } pattern{ commands } END{ commands }'tcp
这条指令和之前的命令有些不一样,他的命令有执行顺序:
ide
第一步:运行BEGIN{ commands }语句块中的语句。函数
第二步:从文件或标准输入(stdin)读取一行。而后运行pattern{ commands }语句块,它逐行扫描文件,从第一行到最后一行反复这个过程。直到文件全部被读取完成。
第三步:当读至输入流末尾时。运行END{ commands }语句块。
BEGIN语句块在awk開始从输入流中读取行以前被运行,这是一个可选的语句块,比方变量初始化、打印输出表格的表头等语句一般可以写在BEGIN语句块中。
END语句块在awk从输入流中读取全然部的行以后即被运行。比方打印所有行的分析结果这类信息汇总都是在END语句块中完毕,它也是一个可选语句块。
pattern语句块中的通用命令是最重要的部分,它也是可选的。假设没有提供pattern语句块,则默认运行{ print },即打印每一个读取到的行。awk读取的每一行都会运行该语句块。
这三个部分缺乏任何一部分均可以。
选项:
-F 指明输入时用到的字段分隔符
-v var=value: 自定义变量
-f scripfile 从脚本文件中读取awk命令
3、awk的变量
变量分为内置和自定义变量
内置变量:
FS:输入字段分隔符,默认为空白字符
[root@localhost(cyn) ~]$ awk -v FS=':' '{print $1,FS,$3}' /etc/passwd #设置默认字符为: root : 0 bin : 1
OFS:输出字段分隔符,默认为空白字符
[root@localhost(cyn) ~]$ awk -v FS=':' -v OFS='!' '{print $1,$3}' /etc/passwd #设置输出为! root!0 bin!1
RS:输入记录分隔符,指定输入时的换行符,原换行符仍有效
[root@localhost(cyn) ~]$ awk -v RS=' ' '{print }' /etc/passwd #之前是按行进行操做,如今是按照RS定义的来,换行符依然是换行符 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin nobody:x:99:99:Nobody:/:/sbin/nologin systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
ORS:输出记录分隔符,输出时用指定符号代替换行符 #制定输出时的换行符
[root@localhost(cyn) ~]$ awk -v RS=' ' -v ORS='###' '{print }' /etc/passwd ftp:x:14:50:FTP###User:/var/ftp:/sbin/nologin nobody:x:99:99:Nobody:/:/sbin/nologin systemd-network:x:192:192:systemd###Network###Management:/:/sbin/nologin dbus:x:81:81:System###message###bus:/:/sbin/nologin polkitd:x:999:998:User###for###polkitd:/:/sbin/nologin
NF:字段数量
###[root@localhost(cyn) ~]$ awk -F: '{print NF}' /etc/passwd 7 7 7 7
NR:行号
[root@localhost(cyn) ~]$ awk '{print NR}' /etc/passwd 1 2 3 4 5 6
FNR:各文件分别计数,行号
[root@localhost(cyn) ~]$ awk '{print FNR}' /etc/fstab /etc/passwd #统计两个文件的行号 1 2 。。。 11 12 1 2
ARGC:命令行参数的个数
[root@localhost(cyn) ~]$ awk '{print ARGC}' /etc/fstab /etc/passwd #最前面的awk也算一个参数为$0 3 3 3 3
ARGV:数组,保存的是命令行所给定的各参数
[root@localhost(cyn) ~]$ awk '{print ARGV[1]}' /etc/fstab /etc/passwd /etc/fstab /etc/fstab [root@localhost(cyn) ~]$ awk '{print ARGV[0]}' /etc/fstab /etc/passwd awk awk [root@localhost(cyn) ~]$ awk '{print ARGV[2]}' /etc/fstab /etc/passwd /etc/passwd /etc/passwd
自定义变量
[root@localhost(cyn) ~]$ awk -v test='hello' '{print test}' /etc/passwd hello hello
4、格式化输出
格式化输出:printf “FORMAT”, item1, item2, ...
(1) 必须指定FORMAT
(2) 不会自动换行,须要显式给出换行控制符,\n
(3) FORMAT中须要分别为后面每一个item指定格式符
格式符:与item一一对应
%c: 显示字符的ASCII码
%d, %i: 显示十进制整数
%e, %E:显示科学计数法数值
%f:显示为浮点数
%g, %G:以科学计数法或浮点形式显示数值
%s:显示字符串
%u:无符号整数
%%: 显示
%自身
修饰符:
#[.#]:第一个数字控制显示的宽度;第二个#表示小数点后精度,%3.1f
-: 左对齐(默认右对齐)
%-15s +:显示数值的正负符号 %+d
[root@localhost(cyn) ~]$ awk -F: '{printf "%-15s%-5s\n",$1,$6}' /etc/passwd root /root bin /bin daemon /sbin
5、awk操做符
算术操做符:
x+y, x-y, x*y, x/y, x^y, x%y
-x: 转换为负数
+x: 转换为数值
字符串操做符:没有符号的操做符,字符串链接
赋值操做符:
=, +=, -=, *=, /=, %=, ^=
++, -
比较操做符: ==, !=, >, >=, <, <=
模式匹配符:
~:左边是否和右边匹配包含
!~:是否不匹配
[root@localhost(cyn) ~]$ awk -F: '($0 ~ /root/ ){print $1}' /etc/passwd #支持正则 root operator
6、awk控制语句
awk支持while,if else,for循环,这部分
利用while计算100以内的和 [root@localhost(cyn) ~]$ awk BEGIN'{i=1;while(i<=100){sum+=i;i++};print sum}' 利用forjisuan 100以内的和 [root@localhost(cyn) ~]$ awk BEGIN'{for(i=1;i<=100;i++){sum+=i};print sum}' 利用for和if else计算奇数和 [root@localhost(cyn) ~]$ awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i};print sum}'
7、awk数组
关联数组:array[index-expression] • index-expression:
(1) 可以使用任意字符串;字符串要使用双引号括起来
(2) 若是某数组元素事先不存在,在引用时,awk会自动建立此元素,并将其值初始化为“空串”
若要判断数组中是否存在某元素,要使用“index in array”格式进行遍历
若要遍历数组中的每一个元素,要使用for循环
for(var in array) {
for-body
}
注意:var会遍历array的每一个索引
[root@centos6(cyn) ~]$ awk -F: '{line[$7]++}END{for(i in line){print i,line[i]}}' /etc/passwd #统计文件中某个单词出现的次数 /sbin/shutdown 1 /bin/bash 1 /sbin/nologin 27 /sbin/halt 1 /bin/sync 1 [root@centos6(cyn) ~]$ netstat -tan|awk '/^tcp/{state[$NF]++}END{for(i in state){print i,state[i]}}' #统计监听出现的次数 ESTABLISHED 1 LISTEN 10
8、awk函数
1.数值处理:
rand():返回0和1之间一个随机数
[root@centos6(cyn) ~]$ awk 'BEGIN{srand(); for (i=1;i<=10;i++)print int(rand()*100) }' 17 4 57 54 43 32 87 90
2.字符串处理:
length([s]):返回指定字符串的长度
sub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并将第一个匹配的内容替换为s
[root@centos6(cyn) ~]$ echo "2018:08:29 10:08:30" |awk 'sub(/:/,"-",$1)' 2018-08:29 10:08:30
gsub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并所有替换为s所表示的内容
[root@centos6(cyn) ~]$ echo "2018:08:29 10:08:30" |awk 'gsub(/:/,"-",$1)' 2018-08-29 10:08:30 [root@centos6(cyn) ~]$ echo "2018:08:29 10:08:30" |awk 'gsub(/:/,"-",$0)' 2018-08-29 10-08-30
split(s,array,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存至array所表示的数组 中,第一个索引值为1,第二个索引值为2,…
[root@centos6(cyn) ~]$ netstat -tan |awk '/^tcp\>/&& !($5 ~ "*") {split($5,ip,":");count[ip[1]]++}END{for(i in count){print i,count[i]}}' 172.18.253.52 1 172.18.253.114 1 172.18.251.79 1 172.18.250.40 1 172.18.254.218 1 172.18.254.139 2
3.自定义函数,awk的函数不须要加权限,直接运行
[root@centos6(cyn) ~]$ vim fun.awk [root@centos6(cyn) ~]$ cat fun.awk function max(a,b){ a>b?var=a:var=b return var } BEGIN{m=3;n=2;print max(m,n)} [root@centos6(cyn) ~]$ awk -f fun.awk 3
9、awk中调用shell命令
system命令
空格是awk中的字符串链接符,若是system中须要使用awk中的变量可使用空格分隔,或者说除了 awk的变量外其余一概用""引用起来。
[root@centos6(cyn) ~]$ awk 'BEGIN{score=100;system("name=zhangsan;echo $name score is "score )}' zhangsan score is 100 [root@centos6(cyn) ~]$ awk BEGIN'{system("hostname")}' centos6