awk 是一个报告生成器,它拥有强大的文本格式化的能力。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。
awk [options] ‘pattern{action}’ file
awk 是逐行处理,用输入分割符(FS)将每行分割成多个字段,经过action处理后又使用输出分割符(OFS)将各字段拼接起来输出。
>> cat awk-test
a1 b1 c1
a2 b2 c2 d2 e2 f2
>> cat awk-test | awk '{print $1,$2,$3,"$4",$5,"hello"}' # 或: awk '{print $1,$2,$3,"$4",$5,"hello"}' awk-test
a1 b1 c1 $4 hello
a2 b2 c2 $4 e2 hello
>> awk -v OFS="-" '{print $1,$2,$3,"$4",$5,"hello"}' awk-test
a1-b1-c1-$4--hello
a2-b2-c2-$4-e2-hell
# 注:
# 某一行缺少某一列时不会输出任何文本
# 当内置变量加上双引号后,会被当成普通文本输出
>> cat awk-test
a1 b1 c1~~a2 b2 c2
>> awk -v RS="~~" '{print $1,$2}' awk-test
a1 b1
a2 b2
>> awk -v RS="~~" -v ORS="****" '{print $1,$2}' awk-test
a1 b1****a2 b2****
>> cat awk-test
a1 b1 c1
a2 b2 c2
>> cat awk-test2
a1 b1 c1
a2 b2 c2
>> awk '{print FILENAME,NR,$1,$2,$3}' awk-test awk-test2
awk-test 1 a1 b1 c1
awk-test 2 a2 b2 c2
awk-test2 3 a1 b1 c1
awk-test2 4 a2 b2 c2
>> awk '{print FILENAME,FNR,$1,$2,$3}' awk-test awk-test2
awk-test 1 a1 b1 c1
awk-test 2 a2 b2 c2
awk-test2 1 a1 b1 c1
awk-test2 2 a2 b2 c2
>> awk 'BEGIN{print ARGV[0],ARGV[1],ARGV[2],ARGC}' awk-test awk-test2
awk awk-test awk-test2 3
>> awk -v aa="hello" -v bb="awk" 'BEGIN{print aa,bb}'
hello awk
>> awk 'BEGIN{aa="hello";bb="awk";print aa,bb}'
hello awk
上面用到的 print 只能实现简单的文本输出功能,并不能对文本格式进行改变。如果想要改变文本的格式,则需要awk中的另一个action:printf。awk中的printf 跟系统的printf命令相似,可参考printf 命令详解。
>> cat awk-test
姓名 科目 成绩~~张小明 语文 88~~李小红 英语 90~~王小斌 数学 100
>> awk -v RS="~~" '{print $1,$2,$3}' awk-test
姓名 科目 成绩
张小明 语文 88
李小红 英语 90
王小斌 数学 100
>> awk -v RS="~~" '{printf "%-4s\t %-4s\t %-4s\n",$1,$2,$3}' awk-test
姓名 科目 成绩
张小明 语文 88
李小红 英语 90
王小斌 数学 100
#注:
# %s:字符串占位符,同理还有%f %d 等
# \t:水平制表符,同理还有\n \r 等转义符
# -: 左对齐
# 4:字符串的显示宽度为4,如果不满足4则用空格填充
pattern是一个行条件表达式,只有满足该条件的行才会被处理。没有模式的情况下(空模式),awk会对每行都进行处理。
>> cat awk-test
张小明 语文 88
李小红 英语 90
王小斌 数学 100
#找出成绩大于90的学生
>> awk '$3>90{print $1,$2,$3}' awk-test
王小斌 数学 100
>> cat awk-test
abcdefg
123456
324ag
#找出全为数字的那一行
>> awk '/^[0-9]*$/{print $0}' awk-test
123456
>> cat awk-test
1 Allen Phillips
2 Green Lee
3 William Aiden James Lee
4 Angel Jack
5 Tyler Kevin
6 Lucas Thomas
#找出第一次出现Lee 到第一次出现Kevin 间的所有行
>> awk '/Lee/,/Kevin/{print $0}' awk-test
2 Green Lee
3 William Aiden James Lee
4 Angel Jack
5 Tyler Kevin
>> cat awk-test
姓名 年龄
张三 15
李四 23
王五 50
>> awk 'NR!=1{if($2<18){print $1"是少年"}else if($2<30){print $1"是青年"}else{print $1"是中年"}}' awk-test
张三是少年
李四是青年
王五是中年
>> awk 'BEGIN{for(i=0;i<10;i++){if(i==3){continue}else if(i>5){break}else{print i}}}'
0
1
2
4
5
>> cat awk-test
aaaaa
bbbb
cccc
ddddd
>> awk 'END{print "finish"}{if(NR==1){next}else if(NR==3){exit}else{print $0}}' awk-test
bbbb
finish
>> awk 'BEGIN{arr[0]=1;arr[1]=2;arr[2]=3;arr["a"]=4;arr["b"]=5;for(ele in arr){print ele}}'
a
b
0
1
2
>> awk 'BEGIN{arr[0]=1;arr[1]=2;arr[2]=3;if(1 in arr)print "arr有下标1";if(!(3 in arr))print "arr没有下标3"}'
arr有下标1
arr没有下标3
>> awk 'BEGIN{arr[0]=1;arr[1]=2;arr[2]=3;print arr[5];if(5 in arr)print "arr自动创建下标5"}'
arr自动创建下标5
# 知识补充 字符串跟数字相加时,字符串会转化成0
>> awk 'BEGIN{a="abc";b="";print a+1;print b+1}'
1
1
#需求:统计每个ip出现的次数
>> cat awk-test
192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.6
192.168.1.3
192.168.1.3
192.168.1.2
>> awk '{ipArray[$1]++} END{for (i in ipArray){print i,ipArray[i]} }' awk-test
192.168.1.1 1
192.168.1.2 2
192.168.1.3 3
192.168.1.6 1
rand函数生成随机数,但是使用rand函数时,需要配合srand函数,否则rand函数返回的值将一直不变。
>> awk 'BEGIN{print rand()}'
0.237788
>> awk 'BEGIN{print rand()}'
0.237788
>> awk 'BEGIN{srand();print rand()}'
0.116798
>> awk 'BEGIN{srand();print rand()}'
0.748171
>> cat awk-test
Allwn Phillips
Green Lee
William Ken Alle
>> awk '{gsub("l","6",$1);print $0}' awk-test
A66wn Phillips
Green Lee
Wi66iam Ken Allen
>> awk '{sub("l","6",$1);print $0}' awk-test
A6lwn Phillips
Green Lee
Wi6liam Ken Allen
>> awk '{print $0,length()}' awk-test
Allwn Phillips 14
Green Lee 9
William Ken Allen 17
>> awk '{print index($0,"ll")}' awk-test
2
0
3
>> awk -v str="a-b-c" 'BEGIN{print "分成"split(str,arr,"-")"份";for(i in arr)print i}'
分成3份
1
2
3
>> awk 'BEGIN{arr["a"]=1;arr["e"]=8;arr["g"]=3; asort(arr); for(i in arr){print i,arr[i]}}'
1 1
2 3
3 8
>> awk 'BEGIN{arr["a"]=1;arr["e"]=8;arr["g"]=3;asort(arr,newArr);\
print "arr数据如下:";\
for(i in arr)print i,arr[i];\
print "newArr 数据如下:";\
for(i in newArr)print i,newArr[i] }'
arr数据如下:
a 1
e 8
g 3
newArr 数据如下:
1 1
2 3
3 8
awk从入门到放弃