awk其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。在比较复杂的shell脚本中经常用到,awk grep sed三个合起来,被俗称为shell三剑客。它是linux系统很强大的文本处理命令,并且方便生成各种报表,语法借鉴了C语言。awk同样支持处理文件和标准输入的内容。
awk最完整的书写格式如下:
awk 'BEGING{command1}{command2}END{command3}' file_name
其中BEGING和END不是必须的,这里保留了。
awk简化版的格式如下:
awk '{command2}' file_name
其中BEGING和END不是必须的,这里省略了。.
一个简单完整的例子
[root@aliyun-hk1 awk]# awk 'BEGIN{print"star"}{print $1}END{print "end"}' ips
star
10.100.12.11
10.100.12.12
10.100.12.89
10.100.12.9
10.100.13.8
10.100.12.11
end
[root@aliyun-hk1 awk]#
BEGIN在脚本运行前执行一次,逐行读入文件的第1列并打印出来,END在脚本运行后执行一次,
一个简化版的例子
[root@aliyun-hk1 awk]# awk '{print $1}' ips
10.100.12.11
10.100.12.12
10.100.12.89
10.100.12.9
10.100.13.8
10.100.12.11
[root@aliyun-hk1 awk]#
逐行读入文件的第1列并打印出来。
如果要一次在一行打印多个变量,使用逗号
[root@aliyun-hk1 awk]# awk '{print $1,"hello","world"}' ips
10.100.12.11 hello world
10.100.12.12 hello world
10.100.12.89 hello world
10.100.12.9 hello world
10.100.13.8 hello world
10.100.12.11 hello world
[root@aliyun-hk1 awk]#
awk会自动用空格分隔不同的变量。
如果要一次执行多个命令,并且不在一行显示,使用分号
[root@aliyun-hk1 awk]# awk '{print $1;print "hello";print "world"}' ips
10.100.12.11
hello
world
10.100.12.12
hello
world
10.100.12.89
hello
world
10.100.12.9
hello
world
10.100.13.8
hello
world
10.100.12.11
hello
world
[root@aliyun-hk1 awk]#
2.awk变量每次读入一行后,三条命令执行一遍。
awk也是一门功能完整的编程语言,所以在各种unix类系统都自带它。awk的变量主要分为内置变量和自定义变量。
以下是常见的内置变量:
$0 当前记录(作为单个变量)
$1~$n 当前记录的第n个字段,字段间由FS分隔
FS 输入字段分隔符 默认是空格
NF 当前记录中的字段个数,就是有多少列
NR 已经读出的记录数,就是行号,从1开始
RS 输入的记录他隔符默 认为换行符
OFS 输出字段分隔符 默认也是空格
ORS 输出的记录分隔符,默认为换行符
ARGC 命令行参数个数
ARGV 命令行参数数组
FILENAME 当前输入文件的名字
IGNORECASE 如果为真,则进行忽略大小写的匹配
ARGIND 当前被处理文件的ARGV标志符
CONVFMT 数字转换格式 %.6g
ENVIRON UNIX环境变量
ERRNO UNIX系统错误消息
FIELDWIDTHS 输入字段宽度的空白分隔字符串
FNR 当前记录数
OFMT 数字的输出格式 %.6g
RSTART 被匹配函数匹配的字符串首
RLENGTH 被匹配函数匹配的字符串长度
SUBSEP \034
自定义变量的使用:
awk像python一样,变量可以不用定义直接使用。
[root@aliyun-hk1 awk]# awk '{print $1;a=NR;print a}' ips
10.100.12.11
1
10.100.12.12
2
10.100.12.89
3
10.100.12.9
4
10.100.13.8
5
10.100.12.11
6
这里把内置变量NR的值赋给了a,并且再打印a,这里只说明如何定义和使用变量。
[root@aliyun-hk1 awk]# awk 'BEGIN{name="robin"}{print $1;a++}END{print a,name}' ips
10.100.12.11
10.100.12.12
10.100.12.89
10.100.12.9
10.100.13.8
10.100.12.11
6 robin
[root@aliyun-hk1 awk]#
3.awk数组经过这个测试我们发现,前面定义的变量name和中间定义的变量a,在END部分都可用直接引用。
假设现在有一个需求,我们拿到了好多IP地址,想快速计算出出现次数前3的IP地址。
使用awk的数组实现
[root@aliyun-hk1 awk]# awk '{ip[$1]++}END{for(i in ip)print(i,ip[i])}' ips|sort|head -n 3
10.100.12.11 2
10.100.12.12 1
10.100.12.89 1
[root@aliyun-hk1 awk]#
使用awk、sort、uniq实现
[root@aliyun-hk1 awk]# awk '{print $1}' ips|sort|uniq -c|head -n 3
2 10.100.12.11
1 10.100.12.12
1 10.100.12.89
[root@aliyun-hk1 awk]#
4.awk循环
待续
5.awk函数待续
6.常见示例:example1 分列显示文本文件内容, $0所有列,$1第一列,$2第二列
[root@aliyun-hk1 linux-shell-test]# awk '{ print $0 }' awk.sh
hello robin
nihao huanhuan
byby joe
[root@aliyun-hk1 linux-shell-test]# awk '{ print $1 }' awk.sh
hello
nihao
byby
[root@aliyun-hk1 linux-shell-test]# awk '{ print $2 }' awk.sh
robin
huanhuan
joe
example2 分列显示标准输入文本
[root@aliyun-hk1 linux-shell-test]# ps -ef|grep python|awk '{ print $0 }'
root 803 1 0 Feb28 ? 00:00:43 /usr/bin/python -Es /usr/sbin/tuned -l -P
root 6820 6216 0 23:21 pts/0 00:00:00 grep --color=auto python
root 19785 1 0 Feb29 ? 00:00:50 python proxyserver.py 11081
[root@aliyun-hk1 linux-shell-test]# ps -ef|grep python|awk '{ print $2 }'
803
6828
19785
example3 使用自定义分隔符分列显示文本,-F ‘=’
[root@aliyun-hk1 linux-shell-test]# awk -F '=' '{print $0 }' awk.sh
hello robin
nihao huanhuan
byby joe
name1=robin
name2=joe
age1=22
[root@aliyun-hk1 linux-shell-test]# awk -F '=' '{print $1 }' awk.sh
hello robin
nihao huanhuan
byby joe
name1
name2
age1
[root@aliyun-hk1 linux-shell-test]# awk -F '=' '{print $2 }' awk.sh
robin
joe
22
example4 分列后显示前N行,NR<=3
[root@aliyun-hk1 linux-shell-test]# awk 'NR<=3 { print $2 }' awk.sh
robin
huanhuan
joe
example5 读取shell中变量,用于awk命令参数
[root@aliyun-hk1 linux-shell-test]# awk -v var=$split_char -F '=' 'NR<=6 { print $1 var }' awk.sh
hello robin=
nihao huanhuan=
byby joe=
name1=
name2=
age1=
example6 拆分标准输入或者文件内容,并重新格式化
[root@aliyun-hk1 linux-shell-test]# echo -e 'line1=hello\nline2=world'|awk -F '=' '{ print $1": "$2 }'
line1: hello
line2: world
[root@aliyun-hk1 linux-shell-test]# awk -F '=' 'NR>3 { print $1": "$2 }' awk.sh
name1: robin
name2: joe
age1: 22
example7 awk也算是一个编程语言,我们先把简单的、最常用的使用方式搞清除了,再来尝试高级的使用。
请打开后自行学习 https://awk.readthedocs.io/en/latest/index.html