log.txt文本内容如下:
1 2 3 4 2 this is a test 3 Are you like awk This's a test 10 There are orange,apple,mongo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 ls -l | awk '{print $1,$5}' $n 代表输出第几列 ls -l | awk '{print $1,$5}' OFS=" | " OFS标识以 " | " 对输出结果分割 awk -F, '{print $1,$2}' log.txt # -F, 使用","分割 awk '$1>2' log.txt 过滤第一列大于2的行 awk '$1==2 {print $1,$3}' log.txt #过滤第一列等于2的行,输出1,3列 ls -l | awk '$5>1000 {print $1,$5}' OFS=" | " 输出ls中大于1000的文件 ls -l | awk '$5>1000 && $5<10000 {print $1,$5}' OFS=" | " 输出ls中大于1000且小于10000的文件 ls -l | awk 'BEGIN{dirNum=0;}{ if($1 ~ /^d/){res[dirNum++]=$9;print dirNum;}} END{ for(i=0;i<dirNum;i++){ print res[i]; } } ' # 输出目录 $9 代表了ls -l的第九列 $1 ~ /^d/ 中呢规则匹配开头是d的
设置普通变量
1 2 3 4 5 6 7 8 9 10 11 12 13 awk -v # 设置变量 $ awk -va=1 '{print $1,$1+a}' log.txt --------------------------------------------- 2 3 3 4 This's 1 10 11 $ awk -va=1 -vb=s '{print $1,$1+a,$1b}' log.txt $1b是直接结合字符串变量 --------------------------------------------- 2 3 2s 3 4 3s This's 1 This'ss 10 11 10s
字符串连接
1 2 3 4 5 6 7 将变量与””符号连接起来运算即可 [chengmo@centos5 ~]$ awk 'BEGIN{a="a";b="b";c=(a""b);print c}' ab 通过”+”连接运算。自动强制将字符串转为整型。非数字变成0,发现第一个非数字字符,后面自动忽略。 [chengmo@centos5 ~]$ awk 'BEGIN{a="a";b="b";c=(a+b);print c}' 0
数组变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 sites["runoob"]="www.runoob.com"; sites["google"]="www.google.com" delete sites["google"]; // 删除 print fruits["google"] 模拟二维数组 array["0,0"] = 100; array["0,1"] = 200; array["0,2"] = 300; array["1,0"] = 400; array["1,1"] = 500; array["1,2"] = 600; # 输出数组元素 print "array[0,0] = " array["0,0"]; print "array[0,1] = " array["0,1"]; print "array[0,2] = " array["0,2"]; print "array[1,0] = " array["1,0"]; print "array[1,1] = " array["1,1"]; print "array[1,2] = " array["1,2"];
数组典型应用
1 2 3 4 1. 用 awk 中查看服务器连接状态并汇总 netstat -an|awk '/^tcp/{++s[$NF]}END{for(a in s)print a,s[a]}' ESTABLISHED 1 LISTEN 20
1 2 3 4 5 6 7 8 9 10 11 2. 统计 web 日志访问流量,要求输出访问次数,请求页面或图片,每个请求的总大小,总访问流量的大小汇总 awk '{a[$7]+=$10;++b[$7];total+=$10}END{for(x in a)print b[x],x,a[x]|"sort -rn -k1";print "total size is :"total}' /app/log/access_logtotal size is :172230 21 /icons/poweredby.png 83076 14 / 70546 8 /icons/apache_pb.gif 18608 a[$7 ]+=$10 表示以第 7 列为下标的数组( $10 列为$7 列的大小),把他们大小累加得到 $7 每次访问的大小,后面的 for 循环有个取巧的地方, a 和 b 数组的下标相同,所以一条 for 语句足矣
条件判断 for循环
1 2 3 4 5 6 7 8 9 10 11 $ awk 'BEGIN { a=30; if (a==10) print "a = 10"; else if (a == 20) print "a = 20"; else if (a == 30) print "a = 30"; }' $ awk 'BEGIN { for (i = 1; i <= 5; ++i) print i }'
自定义函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 # 返回最小值 function find_min(num1, num2) { if (num1 < num2) return num1 return num2 } # 返回最大值 function find_max(num1, num2) { if (num1 > num2) return num1 return num2 } # 主函数 function main(num1, num2) { # 查找最小值 result = find_min(10, 20) print "Minimum =", result # 查找最大值 result = find_max(10, 20) print "Maximum =", result } # 脚本从这里开始执行 BEGIN { main(10, 20) }
awk脚本
1 2 3 4 awk -f {awk脚本} {文件名} 实例: $ awk -f cal.awk log.txt
ls.awk
脚本分为 开头,正文,结尾 三部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 BEGIN { OFS=" | " ; No = "序号" ; Permisson = " 权 限" ; HardLink = "硬链接数" ; SymbolicLinks = "软链接" ; SubDir = "子目录数" ; Owner = "所属用户" ; Size = "大小" ; LastModified = "最近修改" ; Name = "名称" ; no = 0; dirNum = 0; fileNum = 0; Total = 0; printf "-------------------------\n\n" ; printf "[普通文件]: \n" ; printf "%-10s %-6s %-6s %-8s %-8s %-s\n" ,Permisson,HardLink,Owner,Size,LastModified,Name; }; { if ($1 ~ /^d/){ res[Permisson"" dirNum] = $1 ; res[SubDir"" dirNum] = $2 ; res[Owner"" dirNum] = $3 ; res[Size"" dirNum] = $5 ; res[LastModified"" dirNum] = $6 ; res[Name"" dirNum] = $9 ; dirNum++; }else { if (NR == 1){ Total = $2 ; }else { fileNum++; printf "%-15s %-8s %-9s %-13s %-8s %-s \n" , $1 ,$2 ,$3 ,$5 ,$6 ,$9 ; } } } END{ printf "-------------------------\n\n" ; printf "[目录]: \n" ; printf "%-10s %-6s %-6s %-8s %-8s %-s\n" ,Permisson,SubDir,Owner,Size,LastModified,Name; for (i=0;i<dirNum;i++) printf "%-15s %-8s %-9s %-13s %-8s %-s \n" , res[Permisson"" i],res[SubDir"" i],res[Owner"" i],res[Size"" i],res[LastModified"" i],res[Name"" i]; printf "-------------------------\n" ; printf "[总用量]: %s\n" ,Total; printf "[目录数量]: %s\n" ,dirNum; printf "[文件数量]: %s\n" ,fileNum; }
常用字符串函数
字符串函数的应用
替换
1 2 3 awk 'BEGIN{info="this is a test2010test!";gsub(/[0-9]+/,"!",info);print info}' this is a test !test ! 在 info 中查找满足正则表达式, /[0-9]+/ 用”!”替换,并且替换后的值,赋值给 info 未 给 info 值,默认是$0
查找
1 2 awk 'BEGIN{info="this is a test2010test!";print index(info,"test")?"ok":"no found";}' ok
匹配查找
1 2 awk 'BEGIN{info="this is a test2010test!";print match(info,/[0-9]+/)?"ok":"no found";}' ok
截取
1 2 awk 'BEGIN{info="this is a test2010test!";print substr(info,4,10);}' s is a tes
分割
1 2 3 4 awk 'BEGIN{info="this is a test";split(info,tA," ");print length(tA);for(k in tA){print k,tA[k];}}' 4 4 test 1 this 2 is 3 a 1…n 开始
内建变量
变量 描述
$n 当前记录的第n个字段,字段间由FS分隔
$0 完整的输入记录
ARGC 命令行参数的数目
ARGIND 命令行中当前文件的位置(从0开始算)
ARGV 包含命令行参数的数组
CONVFMT 数字转换格式(默认值为%.6g)ENVIRON环境变量关联数组
ERRNO 最后一个系统错误的描述
FIELDWIDTHS 字段宽度列表(用空格键分隔)
FILENAME 当前文件名
FNR 各文件分别计数的行号
FS 字段分隔符(默认是任何空格)
IGNORECASE 如果为真,则进行忽略大小写的匹配
NF 一条记录的字段的数目
NR 已经读出的记录数,就是行号,从1开始
OFMT 数字的输出格式(默认值是%.6g)
OFS 输出记录分隔符(输出换行符),输出时用指定的符号代替换行符
ORS 输出记录分隔符(默认值是一个换行符)
RLENGTH 由match函数所匹配的字符串的长度
RS 记录分隔符(默认是一个换行符)
RSTART 由match函数所匹配的字符串的第一个位置
SUBSEP 数组下标分隔符(默认值是/034)