awk
awk****推荐去看朱双印的博客“awk****从放弃到入门”,写的真的很好,本文的awk****就总结于它。
awk其实是一门编程语音,它支持条件判断、数组、循环等功能。所以,我们也可以把awk理解成一个脚本语言解释器
1、awk基础
1.1、普通模式
awk 【option】 ‘program’ file1,file2
1.2、特殊模式
1) BEGIN和END模块只能有一个。中间的pattern匹配,可以有多个
NR==2{print 1}
2) BEGIN模块,代表awk在处理文本前要做的事。即使不接收文件名,仅仅使用BEGIN模块打印,也能正常输出
awk ‘BEGIN {print “111”,”222”}’
3) END模块,代表awk在处理文本后要做的事
awk ‘{print 2} END{print ‘333’,’444’}’test
1.3、内置变量
1.4、自定义变量
awk除了使用内置变量,还可以自己定义变量。
方法一:-v varname=value 变量名区分字符大小写。-v:设置变量
方法二:在program中定义
1****、-v ****定义
2****、在program****定义
2、printf
awk本身负责文本切割,printf动作则负责格式格式化文本。在了解awk的printf动作前,需要首先了解printf命令
2.1、shell的printf命令
在shell中,echo和printf都是输出文本的命令。echo输出的字符串,会自动在末尾加上\n,
而printf不会。printf的作用是按照我们指定的格式输出文本,所以\n,也需要我们自己指定
echo与printf
注意看3,printf的优势就在于,可以用格式替换符,帮我们处理一长串的str
替换符号
格式替换符
转义字符
修饰符
“.5”表示整数的长度,不足用0补齐
例子
2.2、awk的printf动作
awk的printf动作与shell的printf命令很像,只是要注意几点:
1) 使用printf动作输出的文本不会换行,要自己手动加\n
2) 使用printf动作时,“指定的格式”与“被格式化的文本”间,要用“逗号”隔开
3) 使用printf动作,“格式替换符”与“被格式化的文本”数量一一对应
例子
awk -v FS=':' 'BEGIN{printf "%-10s\t %s\n","用户名称","用户ID"} {printf "%-10s\t %s\n",3}' /etc/passwd
用户名称 用户ID
root 0
bin 1
3、awk模式(Pattern)
3.1、grep与awk的正则对比
grep ‘^root’/etc/passwd
awk ‘/^root/{print $0}’ /etc/passwd
3.2、awk正则的注意点
1)awk命令中的正则是“扩展正则表达式”
2)当使用{x,y}或[[:space]],这种正则时,要加上参数—posix
3)注意对“\”和“.”转义
3.3、awk的行范围模式
两个正则的就是行范围模式,从正则1匹配的行开始,到正则2匹配的行结束
正则匹配符
3.4、例子
4、awk动作总结
4.0、动作拆分
上图的动作分为两个部分:
1) 红线标注:最外侧的括号“{}”。“组合语句”类型的动作,将多个代码组合成代码块
2) 蓝线标注:“print $0”。print是“输出语句”类型的动作
例子
4.1、if动作
如果if对应的{},只有一条命令,可以省略{}
4.2、for动作
4.3、while动作
4.4、do…while动作
do…while循环无论是否满足while的条件,都会先执行一次do里的命令
打印一遍test
打印5遍test
4.5、cotinue和break
1~5,不打印3
打印1~3
4.6、exit
awk中,exit表示跳过后序所有动作,直接执行END内的命令。如果没有END模式,则会直接结束awk命令
只打印1
不会打印$0
4.7、next
next的作用是跳过当前行。直接从下一行 开始处理
跳过第2行
5、awk数组
5.1、基础概念
1)awk中的数组是一个使用字符串作为下标的“关联数组”。
2)我们在使用时,可以用 数字/字符串 作为下标,不过使用数字作为下标时,awk默认会把“数字”下标转换为“字符串”。
3)在awk中,元素的值可以设置为“空”。
4)当一个元素不存在于数组时,如果我们直接引用这个不存在的元素,awk会自动创建这个元素,并且默认为这个元素赋值为“空字符串”
5)在awk中,判断数组中元素是否存在,用“if(下标 in 数组名)”。即判断数组中是否有key
6)使用split函数生成的数组,下标默认是从1开始的
5.2、基本操作
创建数组,直接创建就可以
删除数组中的元素
awk ‘BEGIN{ …;delete huluwa[0]}’
删除整个数组
awk ‘BEGIN{ …;delete huluwa}’
for循环有序遍历数组。只有下标是数字时,通过下标的递增,才能有序遍历
awk ‘BEGIN{ …;for (i=1;i<=3;i++){print i,huluwa[i];} }’
for循环无序遍历数组。因为awk数组本身是无序的关联数组
awk ‘BEGIN{ …;for (i in huluwa){print i,huluwa[i]} }’
实例应用——统计某文件$1 重复出现的次数
awk ‘{count[$1]++} END{ for (i in count ) {print i,count[i]} }’ file
实例应用——统计某文本人名出现次数
awk ‘{ for (i=1;i<=NF;i++) {count[$i]++} } END{ for (a in count) {print a,count[a]} }’
6、awk内置函数
6.1、算术函数
rand函数,srand函数,int函数
rand函数固定打印了0.237788,srand函数固定打印1,两者合用,可生成小于1的随机数
rand函数
awk 'BEGIN{print rand()}'
0.237788
srand函数
awk 'BEGIN{print srand()}'
1
生成小于1的随机数
awk 'BEGIN{srand();print rand()}'
0.319498
通过随机数乘100,在通过int函数取整,生成0~100间的随机数
awk 'BEGIN{srand();print int(100*rand())}'
76
6.2、字符串函数
gsub函数,sub函数
这两个函数用于替换某些 文本
awk ‘{ gsub (“old”,“new”,0}’file
awk ‘{ gsub (“[a-z]”,“new”,0}’file
gsub将指定范围内匹配的字符全部替换为新字符
sub用法与gsub一样,但只替换匹配范围内第一次匹配到的字符
比如某文件就一行,$1=aaa。
gsub(“a”,“b”),则0
sub(“a”,“b”),则$1=baa。
length函数
length函数可获取指定字符串的长度。不指定参数,默认为$0
awk ‘{ for (i=1;i<=NF;i++) {print i)} }’file
index函数
获取指定字符串位于整个字符串中的位置
awk ‘{print index($0,“LEE”)}’file
0
7
0
index函数在每一行中查找LEE,如果该行没有,返回0,该行有,返回位置
split函数
split函数可以切割字符串,帮我们动态生成数组。生成的数组下标从1开始
将ts以“;”分隔,并将分隔后的str保存到huluwa数组中
awk –v ts=”one;two;three”‘BEGIN{ print split(ts,huluwa,”;”)}’
split函数的返回值就是数组长度
split(ts,huluwa,”;”) == 3
6.3、排序函数
asort函数
asort函数根据数组的value值进行排序
asort排序后,原有key将被数字替代
awk 'BEGIN{ t["a"]=66;t["b"]=88;t["c"]=35 ; asort(t) ; for (i in t){print i,t[i]} }'
1 35
2 66
3 88
asort排序时,新建一个数组。t[]不变,新创了new[]
awk 'BEGIN{ t["a"]=66;t["b"]=88;t["c"]=35 ; asort(t,new) ; \
for (i in new){print i,new[i]} }'
asort函数的返回值就是数组的长度
asort(t,new)==3
asorti函数
asorti函数会对原数组的key排序,然后将key作为value生成一个新数组
awk 'BEGIN{ t["a"]=66;t["b"]=88;t["c"]=35;asorti(t,new);for (i in new){print i,new[i]} }'
1 a
2 b
3 c
通过asorti排列原数组
awk 'BEGIN{ t["a"]=66;t["b"]=88;t["c"]=35;asorti(t,new);\
for (i in new){print i,new[i],t[new[i]] } }'
1 a 66
2 b 88
3 c 35
7、三元运算与打印奇偶行
7.1、三元运算
if…else判断用户类型
awk –F : ‘{ if($3<500){usertype=“系统用户”}else{ usertype=“普通用户”};\
print $1,usertype }’/etc/passwd
三元运算符替换if…else
awk –F : ‘{ usertype=$3<500?“系统用户”: “普通用户”;\
print $1,usertype }’/etc/passwd
l $3<500:条件判断
l ?”系统用户”:为真,则“系统用户”赋给usertype
l :“普通用户”:为假,则“普通用户”赋给usertype
三元运算符统计“系统用户”和“普通用户”数量
awk -F: '{$3<500?a++:b++}END{print a,b}' /etc/passwd
7.2、打印奇偶行
打印奇数行
awk ‘a=!a’flie
打印偶数行
awk ‘!(a=!a)’flie
解析:
我们知道awk的正则匹配是
/
但如果我们不加print动作,仅仅有正则,那么会默认打印$0。
awk ‘/正则/’file
而在awk中,非0/非空str表示“真”。0/空表示“假”
注意,这不是正则,‘2’不为0/空,打印file所有
awk '2' file
所以’a=!a’
1) a没有定义,初始化a=‘’,a为“假”
2) !a为“真”
3) a=!a,a变为“真”,打印第1行
4) !a又变为“假”,不打印第2行
‘!(a=!a)’
1)a=!a为真,!(a=!a)为假,不打印 第1行
2)a=!a为假,!(a=!a)为真,打印第2行
8、参考文档
awk从放弃到入门 (http://www.zsythink.net/?s=awk)
awk用法(使用入门) (https://www.cnblogs.com/emanlee/p/3327576.html)
官方文档 (https://www.gnu.org/software/gawk/manual/html_node/index.html#SEC_Contents)