awk是一种处理文本文件的语言,是一个强大的文本分析工具。awk其实不仅仅是工具软件,还是一种编程语言。awk是以文件的一行内容为处理单位的。awk读取一行内容,然后根据指定条件判断是否处理此行内容,若此行文本符合条件,则按照动作处理文本,否则跳过此行文本,读取下一行进行判断。

 awk是”Aho Weiberger and Kernighan”三个作者的姓的第一个字母。

 由于awk天生提供对文件中文本分列进行处理,所以如果一个文件中的每行都被特定的分隔符(常见的是空格)隔开,我们可以将这个文件看成是由很多列的文本组成,这样的文件最适合用awk进行处理,其实awk在工作中很多时候被用来处理log文件,进行一些统计工作等。

1.命令格式:

1
2
3
awk [选项] 'BEGIN{commands} pattern{commands} END{commands}' file

awk [选项] '脚本命令' 文件名

echo ‘1|2|3|4’ | awk -F ‘|’ ‘{print $3}’
echo | awk ‘{print “hello world!”}’

2.命令功能:

 awk是一种处理文本文件的语言,是一个强大的文本分析工具

3.命令参数:

1
2
3
4
5
6
7
8
-F fs, 指定以fs作为输入行的分隔符,awk命令默认分隔符为空格或制表符。
-f file, 从脚本文件中读取awk脚本指令,以取代直接在命令行中输入指令。
-v var=val, 在执行处理过程之前,设置一个变量var,并给其设备初始值为val。

Begin{}, 初始化代码块,在对每一行进行处理之前,初始化代码,主要是引用全局变量,设置FS分隔符
//, 匹配代码块,可以是字符串或正则表达式
{}, 命令代码块,包含一条或多条命令,多条命令用;隔开
END{}, 结尾代码块,在对每一行进行处理之后再执行的代码块,主要是进行最终计算或输出结尾摘要信息

4.awk变量:

awk内建变量:

1
2
3
4
5
6
7
8
9
10
11
$0, 当前记录,当前行所有列
$1~$n, 当前记录的第n个字段,字段间由FS分隔
FS, 输入域分隔符,等价于命令行-F,默认为空格
NF, 当前记录中的字段个数,就是有多少列,列总数,$NF则表示最后一列
NR, 已经读取的记录数,就是第几行,从1开始
FNR, 当前记录数
RS, 控制记录分隔符,默认为换行符
OFS, 输出字段分隔符 默认也是空格
ARGC, 命令行参数个数
ARGV, 命令行参数排列
FILENAME awk浏览的文件名

自定义变量类型:

1
2
echo | awk 'i="hello world"{print i}'
echo | awk 'i=1122 {print i}'

数组:

1
echo | awk '{a[1]="hello";a[2]="world!";print a[1],a[2]}'

5.awk常用逻辑运算

1
2
3
4
5
6
7
8
9
?                       条件表达操作符
|| && ! 并、与、非
~ !~ 匹配操作符,包括匹配 不匹配
\+ - * / % ^ 算术操作符
++ -- 前缀和后缀
= += *= / = %= ^ = 赋值操作符
< <= == != >= > 关系操作符
BEGIN 在输出界面第一行输出相关
END 在输出界面最后一行输出相关

6. awk条件判断

1.直接在最外层:

1
echo '11 22' | awk '$1==11{print $2}'

2.使用if语句:

1
echo '11 22' | awk '{if($1==11) print $2}'

3.与或非:

1
2
3
4
5
6
#
echo '11 22' | awk '{if(($1==11) && ($2==22)) print $2}'
#
echo '11 22' | awk '{if(($1==10) || ($2==22)) print $2}'
#
echo '11 22' | awk '{if($1!=10) print $2}'

4.匹配:

1
2
3
4
5
6
~      模糊匹配
== 精确匹配
!~ 不匹配
# 不懂??????为啥
echo 'ansible new switf' | awk '{if($1 ~ i) print $1}'
echo 'ansible new switf' | awk '{if($1 !~ 0) print $1}'

5.正则匹配

1
2
3
4
5
6
# 查看包含root的行
last |awk '/root/{print $0}'
# 查看roo出现0次或多次的行
last |awk '/roo*/{print $0}'
# 查看已root开头的行
last |awk '/^root /{print $0}'

7. awk循环

for(i=1;i<=10;i++):类似C等语言的循环

1
2
3
# 使用awk将每行插入一个符号"|"和tab建
# NF:每一行所拥有的总字段数
last |awk '{for(i=1;i<=NF;i++){printf $i "|\t"} print ""}'

for(i in 数组):类似shell

1
echo|awk 'BEGIN{a[1]=1;a[2]=2}END{for(i in a) print i,a[i]}'

8. 常用内置函数

1
2
3
4
5
6
7
8
9
10
gsub(r,s)          在整个$0中用s替代r,相当于sed 's///g'
gsub(r,s,t) 在整个t中用s替代r
index(s,t) 返回s中字符串t的第一位置
length(s) 返回s长度
match(s,r) 测试s是否包含匹配r的字符串
split(s,a,fs) 在fs上将s分成序列a
sprint(fmt,exp) 返回经fmt格式化后的exp
sub(r,s) 用$0中最左边最长的子串代替s,相当于 sed 's///'
substr(s,p) 返回字符串s中从p开始的后缀部分
substr(s,p,n) 返回字符串s中从p开始长度为n的后缀部分

9.格式化输出

1
awk '{printf  "%-5s %.2d",$1,$2}' file

说明:

1
2
3
4
5
printf 表示格式输出
% 格式化输出分隔符
-8 表示长度为8个字符
s 表示字符串类型
d 表示小数

10.使用实例:

实例1:打印指定倒数字段数:

1
2
# 利用NF打印倒数字段,比如打印倒数第2行
last |awk '{print $(NF-1)}'

实例2:打印文件第1000行到2000行

1
2
awk '1000<=FNR && FNR <=2000' file
awk '{if(1000<=FNR && FNR<=2000) print $0}' file

实例3:使用for循环、数组、自加对netstat的tcp状态统计

1
netstat -an |awk '/^tcp/ BEGIN{s[$NF]++} END{for(a in s) print a,s[a]}'

实例4:替换

eg: test.txt:

1
2
3
zhangsan 70 99 88 77 good
lisi 90 77 66 88 good
sansan 80 88 78 89 good

命令:

1
awk '{if($2>=90) gsub($NF,"Very Good")} {print $0}' test.txt

结果:

1
2
3
zhangsan 70 99 88 77 good
lisi 90 77 66 88 Very Good
sansan 80 88 78 89 good