主页

索引

模块索引

搜索页面

awk命令

语法:

#!/bin/awk -f

awk [ -F fs ] [ -v var=value ] [ 'prog' | -f progfile ] [ file ...  ]

说明:

$0表示整个行(记录)
-v <var>=<value>   //赋值后可以d {}里面使用

内置变量 => NF:当前记录中的字段个数:

>>cat c.txt
1:2:3
1:2
>>awk -F ':' '{print NF}' c.txt
3
2
#可用于字段数过滤
>>awk -F ':' '{if(NF==3)print}' c.txt
1:2:3

内置变量 => 分隔:

RS:记录分隔符变量,缺省为"\n",
缺省情况下,awk把一行看作一个记录;
如果设置了RS,那么awk按照RS来分割记录:

>>cat d.txt
hello world;I am a boy;happy
>>awk 'BEGIN{RS=";"}{print}' d.txt
hello world
I am a boy
happy

内置变量 => ORS: 输出记录分隔符,缺省为换行符,控制每个print语句后的输出符号:

>> cat c.txt
1:2:3
1:2
>> awk 'BEGIN{ORS=";"}{print NF}' c.txt
1;1;

内置变量 => NR: 已经读出的记录数, FNR: 当前文件的记录数:

输入文件a.txt和b.txt,由于先扫描a.txt
所以扫描a.txt的时候必然有NR==FNR,然后扫描b.txt的时候,FNR从1开始计数
而NR则接着a的行数继续计数,所以NR > FNR
awk 'NR==FNR{print} NR>FNR{print}' a.txt b.txt

内置变量 => FS:字段分隔符:

awk -F ':' '{print}'a.txt

awk 'BEGIN{FS=":"}{print}' a.txt
是一样的

内置变量 => OFS:输出字段分隔符(缺省为:space:):

>>cat b.txt
1:2:3
4:5:6
>>awk -F ':' 'BEGIN{OFS=";"}{print $1,$2,$3}' b.txt
#那么把OFS设置成";"后就会输出
1;2;3
4;5;6

awk的内置函数:

显示<testAwk>文件中行号与第1个字段:
awk '{printf"%03d   %s\n",NR,$1}' <testAwk>

显示文本文件<mydoc>匹配(含有)字符串"sun"的所有行:
awk '/sun/{print}' <mydoc>
or
awk '/sun/' <mydoc>   # 显示整个记录(全行)是awk的缺省动作

第一个匹配 ``Sun`` 或 ``sun`` 的行与第一个匹配 ``Moon`` 或 ``moon`` 的行之间的行,并显示到标准输出上:
awk '/[Ss]un/,/[Mm]oon/ {print}' <myfile>

下面的示例显示了内置变量和内置函数length:
awk 'length($0)>80 {print NR}' <myfile>


检查其中的passwd字段(第二字段)是否为"x",如不为"x", 则表示该用户没有设置密码:
awk -F: '$2=="x" {printf "%s no password!\n", $1}' /etc/passwd

awk的流程控制:

BEGIN和END(``<fileName>`` 文件字段间用 ``:`` 分隔):
// 取出文件中的第三列字段, 并最終求和
awk 'BEGIN \
>{ FS=":";print "统计销售金额";total=0}
>{print $3;total=total+$3;}
>END
>{printf "销售金额总计:%.2f",total}' <fileName>

流程控制语句:
if..else
while
do-while
for(<1>;<2>;<3>)

实例:

取出用户列表:
cat /etc/passwd | awk -F: '{print $1}'

分析nginx日志文件 ``access.log`` 获得访问前10位的ip地址:
awk '{print $1}' access.log |sort|uniq -c|sort -nr|head -10

for循环:
awk 'BEGIN{for(i=1;i<=10;i++)print i;}'

其他小示例:

打印所有以模式no或so开头的行:
awk '/^(no|so)/' <fileName>

如果记录以n或s开头,就打印这个记录:
awk '/^[ns]/{print $1}' <filename>

如果第一个域以两个数字结束就打印这个记录:
awk '$1 ~/[0-9][0-9]$/{print $1} <filename>

如果第一个等于100或不等于50或者第二个域小于50,则打印该行:
awk '$1 ==100 || $1 != 50 || $2 < 50' <filename>

如果记录包含正则表达式test,则第一个域加10并打印出来:
awk '/test/{print $1 + 10}' <filename>

如果第一个域大于5则打印前面的表达式值, 否则打印后面的表达式值:
awk '{print ($1 > 5 ? "ok "$1: "error"$1)}' <filename>

打印以正则表达式root开头的记录到以正则表达式mysql开头的记录范围内的所有记录:
awk '/^root/,/^mysql/' <filename>

查出nginx日志中非200:

tail -f access4.log | awk -F '-\^-' '{if($2!~"200"){printf("%s",$0);}}'
// nginx日志如下
zgapi4.taojoy.com.cn : 80 -^- 200 -^- [08/Jul/2016:20:11:32 +0800] -^- 180.97.88.2 \
  -^- /v5/goods/detail?aimuid=1602320&ghid=1063665&sign=4e8de70fc307e595d137222a994da2f9 -^- - -^- "-" -^- \
  "7color zeroshop_ios/5.0 (iPhone; iOS 9.3.2; Scale/2.00)" -^- "124.127.155.90" -^- 1241 -^- 0.036 -^- -\
  -^- http_headers:"app=zeroshop_ios&version=5.0&zgid=2E67E424-4181-4227-8BD8-AEA7F9DF23FC&os=ios&\
  timestamp=1\467979892&uid=1602320&token=a87513dd83fa7ff83d839eda1463555f&channel=appStore"
find src/* | grep erl | awk -F'/' '{print "mv "$0 " apps/octopuscloud/"$0}'

实例:

 1if [ "$1" == "" ]; then
 2        logfile="/var/nginx/logs/access.log"
 3else
 4        logfile=$1
 5fi
 6
 7tail -n 100000 $logfile|awk -F '<->' '{
 8        resp_time=substr($10,5)
 9        app_time=substr($19,5)
10        d=resp_time-app_time
11        if(resp_time > 0 && app_time >0 &&  d>=0 && d<2000) {
12                n++
13                t+=d
14                if(d>1000) {
15                        #print $0
16                }
17        }
18}END{
19        print n,t,t/n
20}'

主页

索引

模块索引

搜索页面