awk是一门模式匹配的编程语言,因为它的主要功能是用于匹配文本并处理,同时它有一些编程语言才有的语法,例如函数、分支循环语句、变量等等,当然比起我们常见的编程语言,Awk相对比较简单。
是一种编程语言,对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出(即管道)。它支持用户自定义函数和 动态正则表达式等先进功能。处理方式是 逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行操作。如果没有指定处理动作,则把匹配的行显示到标准输出 (屏幕),即默认处理动作是print;如果没有指定模式,则所有被操作所指定的行都被处理,即默认指定模式是全部。
AWK取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的Family Name的首字符
像shell一样,awk也有好几种,常见的如awk、nawk、mawk、gawk,
语法
awk [选项参数] 'script(awk脚本)' var=value file(s)
或
awk [选项参数] -f scriptfile var=value file(s)
参数:
-F ERE:定义字段分隔符,该选项的值可以是扩展的正则表达式(ERE):如 awk -F: ‘{print}’ test.txt 或者awk -F’:’ ‘{print}’ test.txt或者 awk -F’[:]’ ‘{print}’ test.txt
-f progfile:指定awk脚本,可以同时指定多个脚本,它们会按照在命令行中出现的顺序连接在一起;
-v assignment:定义awk变量,形式同awk中的变量赋值,即name=value,赋值发生在awk处理文本之前;变量名为关键字则报错
一段awk脚本是由多个’pattern { action }’序列组成的。action是一个或者多个语句,它在输入行匹配pattern的时候被执行。如果pattern为空,表明这个action会在每一行处理时都会被执行。
BEGIN语句块在程序开始执行,只执行一次 BEGIN{} - BODY语句块对每一行执行 /patern/{} - END语句块程序最后执行,执行一次 END{}
awk -v var=1 'BEGIN {print "BEGIN: " var} {print "PROCESS: " var} END {print "END: " var }' test.txt
awk 'BEGIN {print "BEGIN: " var} {print "PROCESS: " var} END {print "END: " var }' var=1 test.txt
awk 'BEGIN {print "BEGIN: " var} {print "PROCESS: " var} END {print "END: " var }' test.txt var=1
awk 'BEGIN {print "BEGIN: " var} {print "PROCESS: " var} END {print "END: " var }' test.txt var=1 test2.txt
–dump-variables [=file]:输出排序好的全局变量列表和他们最终的值到文件中默认文件是awkvars.out
[root@VM_0_9_centos zhimin.xu]# awk --dump-variables ''
[root@VM_0_9_centos zhimin.xu]# cat awkvars.out
ARGC: 1
ARGIND: 0
ARGV: array, 1 elements
BINMODE: 0
CONVFMT: "%.6g"
ERRNO: ""
FIELDWIDTHS: ""
FILENAME: ""
FNR: 0
FPAT: "[^[:space:]]+"
FS: " "
IGNORECASE: 0
LINT: 0
NF: 0
NR: 0
OFMT: "%.6g"
OFS: " "
ORS: "\n"
RLENGTH: 0
RS: "\n"
RSTART: 0
RT: ""
SUBSEP: "\034"
TEXTDOMAIN: "messages"
[root@VM_0_9_centos zhimin.xu]#
awk –help :不做介绍
–lint[=fatal]选项: 允许检查程序的不兼容性或者模棱两可的代码,当提供参数 fatal的时候,它会对待Warning消息作为Error。
awk ‘BEGIN {LINT = 1; a}’
–posix 选项 : 该选项开启严格的POSIX兼容。
–profile[=file]选项: 该选项会输出一份格式化之后的程序到文件中,默认文件是 awkprof.out。
awk --profile 'BEGIN{printf"---|Header|--\n"} {print} END{printf"---|Footer|---\n"}' marks.txt > /dev/null
cat awkprof.out
8个内建变量:Awk将一个文本文件视为一个文本数据库,因此它也有记录和字段的概念。
假如有以下文件为例
[root@VM_0_9_centos zhimin.xu]# awk '{print $0} ' test.txt
tom 1413101-12 78 76 69
cat 1267102-22 30 45 80
jack 1306123-08 66 77 88
aid 1511122-30 77 88 50
alice 1211102-20 88 99 95
tiger 1314104-11 34 45 56
[root@VM_0_9_centos zhimin.xu]#
1.FS(Field Separator) 字段分隔符, 默认按 空格 分隔为字段变量, 1, 1 , 2…等, NF表示最后一个字段, N F 表 示 最 后 一 个 字 段 , (NF-1)表示倒数第二个($0表示整行记录)。FS可以是任意的字符串或者正则表达式,如-F。如果没有Sn则输出空,不会报错
OFS(Output Field Separator) , 默认以 空格 字符作为输出分隔符的
NF(Number for Field)表示的是,一条记录的(以FS分隔)字段的数目
[root@VM_0_9_centos zhimin.xu]# awk -F'[ -]' 'BEGIN{OFS="*";}{print NF,$1,$2,$3}' test.txt
6*tom*1413101*12
6*cat*1267102*22
6*jack*1306123*08
6*aid*1511122*30
6*alice*1211102*20
6*tiger*1314104*11
[root@VM_0_9_centos zhimin.xu]# awk 'BEGIN{OFS=":";FS=" "}{print NF,$1,$2}' test.txt
5:tom:1413101-12
5:cat:1267102-22
5:jack:1306123-08
5:aid:1511122-30
5:alice:1211102-20
5:tiger:1314104-11
awk ‘BEGIN{OFS=”_”;FS=”-“}{print
1,
1
,
2}’ test.txt <==> awk ‘BEGIN{FS=”-“}{print
1,"′′,
1
,
"
"
,
2}’ test.txt
2.RS(Record Separator)记录分隔符。读取文件时,默认将一行作为一条记录。
ORS:(Output Record Separator),每条记录在输出时候会用分隔符隔开,
[root@VM_0_9_centos zhimin.xu]# awk 'BEGIN{RS="\n";ORS="|"}{print $1,$2,$3}' test.txt
tom 1413101-12 78|cat 1267102-22 30|jack 1306123-08 66|aid 1511122-30 77|alice 1211102-20 88|tiger 1314104-11 34|[root@VM_0_9_centos zhimin.xu]#
NR(Number of Record) 表示的是已经读过的总记录数目,或者说行号(不一定是一个文件,可能是多个)。
FNR(File Number of Record) 表示的是当前文件读过的总记录数目,即行数
FILENAME表示当前正在输入的文件的名字。 AWK 可以接受读取很多个文件去处理。
[root@VM_0_9_centos zhimin.xu]# awk 'BEGIN{print "FILENAME NR FNR NF message";OFS=" | "}{print FILENAME,NR,FNR,NF,$0}' test.txt test2.txt
FILENAME NR FNR NF message
test.txt | 1 | 1 | 5 | tom 1413101-12 78 76 69
test.txt | 2 | 2 | 5 | cat 1267102-22 30 45 80
test.txt | 3 | 3 | 5 | jack 1306123-08 66 77 88
test.txt | 4 | 4 | 5 | aid 1511122-30 77 88 50
test.txt | 5 | 5 | 5 | alice 1211102-20 88 99 95
test.txt | 6 | 6 | 5 | tiger 1314104-11 34 45 56
test2.txt | 7 | 1 | 6 | tom 1413101-12 78 76 69 523452
test2.txt | 8 | 2 | 9 | cat 1267102-22 30 45 80 23 23 234 234
test2.txt | 9 | 3 | 9 | jack 1306123-08 66 77 88 234 23 2 dssds
test2.txt | 10 | 4 | 8 | aid 1511122-30 77 88 50 sf 34 134
test2.txt | 11 | 5 | 5 | alice 1211102-20 88 99 95
test2.txt | 12 | 6 | 6 | tiger 1314104-11 34 45 5614 14
[root@VM_0_9_centos zhimin.xu]#
函数-内建函数(部分)+用户自定义函数
close(expr):关闭管道文件
getline 该命令让awk读取下一行内容
[root@VM_0_9_centos zhimin.xu]# cat test.txt
tom 1413101-12 78 76 69
cat 1267102-22 30 45 80
jack 1306123-08 66 77 88
aid 1511122-30 77 88 50
alice 1211102-20 88 99 95
tiger 1314104-11 34 45 5
[root@VM_0_9_centos zhimin.xu]# awk '{getline; print $0}' test.txt
cat 1267102-22 30 45 80
aid 1511122-30 77 88 50
tiger 1314104-11 34 45 5
自定义函数
[root@VM_0_9_centos zhimin.xu]# awk -v a=1 -v b=5 'function sumTest(x,y){return x+y}BEGIN {print a,"+",b,"=",sumTest(a,b);}'
1 + 5 = 6
输出重定向
1.重定向操作符:跟在print和printf函数的后面。>用于将输出写入到指定的文件中,如果文件中有内容则覆盖,而>>则为追加模式写入。
awk 'BEGIN { print "Hello, World !!!" >> " a.txt" }'
2.管道:
实例
计算某一ip 请求 接口次数
[zhimin.xu@l-monitoring1.wh.f.cn1 /home/q/www/monitoring.qunar.com/logs]$ awk '{a[$1]++} END {for(i in a) print i,"--",a[i]}' access.2018-04-24.log
10.88.77.10 -- 2696
10.88.77.130 -- 2845
10.88.77.11 -- 2701
10.95.17.229 -- 33
10.86.236.67 -- 39
10.88.77.131 -- 2715
10.86.236.68 -- 50
10.88.77.132 -- 2651
10.88.105.196 -- 280
10.88.77.133 -- 2769
10.88.105.197 -- 344
10.88.77.134 -- 2625
10.88.77.135 -- 2694
10.88.192.132 -- 2869
10.95.22.4 -- 2641
10.88.192.133 -- 2884
.....
打印超过10个字符的行
[root@VM_0_9_centos zhimin.xu]# awk 'length>23' test.txt
jack 1306123-08 66 77 88
alice 1211102-20 88 99 95
tiger 1314104-11 34 45 5
[root@VM_0_9_centos zhimin.xu]# awk 'length($0)>23' test.txt
jack 1306123-08 66 77 88
alice 1211102-20 88 99 95
tiger 1314104-11 34 45 5
按连接数查看客户端IP
netstat -ntu | awk ‘{print $5}’ | cut -d: -f1 | sort | uniq -c | sort -nr