1.awk 是什么?
The basic function of awk is to search files for lines (or other units of text) that contain certain patterns. When a line matches one of the patterns, awk performs specified actions on that line. awk continues to process input lines in this way until it reaches the end of the input files.
When you run awk, you specify an awk program that tells awk what to do. The program consists of a series of rules (it may also contain function definitions, an advanced feature that we will ignore for now; see User-defined). Each rule specifies one pattern to search for and one action to perform upon finding the pattern.
总的来说 “awk”其实是一种文本处理语言,至于处理那些文本?怎么处理?则就是你要指定的rules。
以前就简简单单的认为awk 就是分析分析linux命令输出的工具,看来还是too young 。
2.awk 怎么用?
1.awk命令行,你可以象使用普通UNIX命令一样使用awk,在命令行中你也可以使用awk程序设计语言,虽然awk支持多行的录入,但是录入长长的命令行并保证其正确无误却是一件令人头疼的事,因此,这种方法一般只用于解决简单的问题。当然,你也可以在shell script程序中引用awk命令行甚至awk程序脚本。
2.使用-f选项调用awk程序。awk允许将一段awk程序写入一个文本文件,然后在awk命令行中用-f选项调用并执行这段程序。具体的方法我们将在后面的awk语法中讲到。
3.awk的用法举例
先说awk 语言,然后再说 awk的命令行的方式 。awk命令行方式就是把awk脚本放在命令行中去,这样就比较方便每次操作。
a.awk 脚本:
$awk -f action.awk test.log
ps:
- action.awk awk脚本
- test.log 待处理文件
我们需要注意两个关键词BEGIN和END。
- BEGIN{ 这里面放的是执行前的语句 }
- END {这里面放的是处理完所有的行后要执行的语句 }
- {这里面放的是处理每一行时要执行的语句}
假设有这么一个文件(学生成绩表):
$ cat score.txt
Marry 2143 78 84 77
Jack 2321 66 78 45
Tom 2122 48 77 71
Mike 2537 87 97 95
Bob 2415 40 57 62
我们的awk脚本如下:
$ cat cal.awk
#!/bin/awk -f
#运行前
BEGIN {
math = 0
english = 0
computer = 0
printf "NAME NO. MATH ENGLISH COMPUTER TOTAL\n"
printf "---------------------------------------------\n"
}
#运行中
{
math+=$3
english+=$4
computer+=$5
printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5
}
#运行后
END {
printf "---------------------------------------------\n"
printf " TOTAL:%10d %8d %8d \n", math, english, computer
printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR
}
我们来看一下执行结果:
$ awk -f cal.awk score.txt
NAME NO. MATH ENGLISH COMPUTER TOTAL
---------------------------------------------
Marry 2143 78 84 77 239
Jack 2321 66 78 45 189
Tom 2122 48 77 71 196
Mike 2537 87 97 95 279
Bob 2415 40 57 62 159
---------------------------------------------
TOTAL: 319 393 350
AVERAGE: 63.80 78.60 70.00
总得来说就是先设置变量,然后读取每行数据(也可以是几行),操作数据,输出。
awk内建变量:
变量 | 描述 |
---|---|
$n | 当前记录的第n个字段,字段间由FS分隔(默认是空格,和Tab) |
$0 | 输出所有的列 |
ARGC | 命令行参数的数目 |
ARGIND | 命令行中当前文件的位置(从0开始算) |
ARGV | 包含命令行参数的数组 |
CONVFMT | 数字转换格式(默认值为%.6g)ENVIRON环境变量关联数组 |
ERRNO | 最后一个系统错误的描述 |
FIELDWIDTHS | 字段宽度列表(用空格键分隔) |
FILENAME | 当前文件名 |
FNR | 同NR,但相对于当前文件 |
FS | 字段分隔符(默认是任何空格) |
IGNORECASE | 如果为真,则进行忽略大小写的匹配 |
NF | 当前记录中的字段数(改行的第几列) |
NR | 当前记录数(第几行) |
OFMT | 数字的输出格式(默认值是%.6g) |
OFS | 输出字段分隔符(默认值是一个空格) |
ORS | 输出记录分隔符(默认值是一个换行符) |
RLENGTH | 由match函数所匹配的字符串的长度 |
RS | 记录分隔符(默认是一个换行符) |
RSTART | 由match函数所匹配的字符串的第一个位置 |
SUBSEP | 数组下标分隔符(默认值是/034) |
内置变量说明:
$ awk 'BEGIN{printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s\n","FILENAME","ARGC","FNR","FS","NF","NR","OFS","ORS","RS";printf "---------------------------------------------\n"} {printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s\n",FILENAME,ARGC,FNR,FS,NF,NR,OFS,ORS,RS}' log.txt
FILENAME ARGC FNR FS NF NR OFS ORS RS
---------------------------------------------
log.txt 2 1 5 1
log.txt 2 2 5 2
log.txt 2 3 3 3
log.txt 2 4 4 4
$ awk -F\' 'BEGIN{printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s\n","FILENAME","ARGC","FNR","FS","NF","NR","OFS","ORS","RS";printf "---------------------------------------------\n"} {printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s\n",FILENAME,ARGC,FNR,FS,NF,NR,OFS,ORS,RS}' log.txt
FILENAME ARGC FNR FS NF NR OFS ORS RS
---------------------------------------------
log.txt 2 1 ' 1 1
log.txt 2 2 ' 1 2
log.txt 2 3 ' 2 3
log.txt 2 4 ' 1 4
# 输出顺序号 NR, 匹配文本行号
$ awk '{print NR,FNR,$1,$2,$3}' log.txt
---------------------------------------------
1 1 2 this is
2 2 3 Are you
3 3 This's a test
4 4 10 There are
# 指定输出分割符
$ awk '{print $1,$2,$5}' OFS=" $ " log.txt
---------------------------------------------
2 $ this $ test
3 $ Are $ awk
This's $ a $
10 $ There $
awk运算符:
运算符 | 描述 |
---|---|
= += -= = /= %= ^= *= | 赋值 |
?: | C条件表达式 |
| | |
&& | 逻辑与 |
~ ~! | 匹配正则表达式和不匹配正则表达式 |
< <= > >= != == | 关系运算符 |
+ - | 加,减 |
* / & | 乘,除与求余 |
+ - ! | 一元加,减和逻辑非 |
^ * | 求幂 |
++ – | 增加或减少,作为前缀或后缀 |
$ | 字段引用 |
in | 数组成员 |
b.awk 命令行:
熟悉了awk 脚本后,再来用awk 命令行工具就很容易了。就是在脚本内容比较少的时候把所有的东西放在一行中就OK啦。
awk [选项参数] 'script' var=value file(s)
选项参数说明:
1.-F fs or --field-separator fs
指定输入文件折分隔符,fs是一个字符串或者是一个正则表达式,如-F:。
2.-v var=value or --asign var=value
赋值一个用户定义变量。
基本用法:
$cat test.log
2 this is a test
3 Are you like awk
This's a test
10 There are orange,apple,mongo
# 每行按空格或TAB分割,输出文本中的1、4项
$ awk '{print $1,$4}' test.log
---------------------------------------------
2 a
3 like
This's
10 orange,apple,mongo
# 格式化输出
$ awk '{printf "%-8s %-10s\n",$1,$4}' log.txt
---------------------------------------------
2 a
3 like
This's
10 orange,apple,mongo
$cat tt.log
2016-11-15 15:18:53 flow*netflow-udp*0006a030*1013400.0*1015100.0
2016-11-15 15:19:23 req*allocate*0006a030*15.0*0.0
2016-11-15 15:19:23 req*auth*0006a030*125.0*30.0
2016-11-15 15:19:23 req*binding*0006a030*0.0*0.0
2016-11-15 15:19:23 req*channelbind*0006a030*20.0*0.0
2016-11-15 15:19:23 req*refresh*0006a030*35.0*0.0
2016-11-15 15:19:32 online*turn_delay_time*0006a030*0.0
2016-11-15 15:19:32 online*turn_lost_packs_rates*0006a030*0.0
2016-11-15 15:19:35 online*turn_delay_time*0006a030*0.0
2016-11-15 15:19:35 online*turn_lost_packs_rates*0006a030*0.0
#以 "*"为分隔符,统计规定时间段内 最后两列的和
$cat tt.log |awk '$2>"15:19:20"&&$2<"15:19:35"' | awk -F"[*]" '{for(i=0;i<2;i++){sum[i]+=$(i+4) }} END {print sum[0] , sum[1]}'
输出:195 30
awk的基本使用就介绍到这里了,以后遇见啥新奇的用法再补充。
参考链接:
linux awk 命令