1、简介
awk来自于其创始人Alfred Aho 、Peter Weinberger 和Brian Kernighan的首个字母。主要用于文本数据格式处理,特别适用于处理每行由多个字段组成的文本数据。
awk也是一种“样式扫描和处理语言”,适用于文本处理和报表生成,其语法借鉴了C和Pascal等语言的精华,允许用户创建简短的程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表等功能。
grep、sed和awk被称为Linux系统中的“文本三剑客”,它们各自的最佳应用场景总结如下:
- grep:使用正则表达式搜索文本,并把匹配的行打印出来,是强大的文本搜索工具;
- sed:用于编辑匹配到的文本,是一种流编辑器;
- awk:能够对文本进行复杂的格式处理,是一种处理文本的工具。
2、基本语法
awk每次读取文本文件的一行,然后以该行中的每个字段为最小处理单位。
awk通过指定分隔符(如空格、Tab、分号或冒号等)将一行分为多个字段,依次用 $1、$2 ... $n等位置变量表示第一个字段、第二个字段... 第n个字段。其中$0表示当前行。
awk每接收文件的一行,就执行相应的命令,其命令格式如下:
awk [选项] '模式 {操作}' [文件名]
(1)awk命令的常用选项如下表所示。
选项 | 含义 |
-e | 指定源码文件 |
-f | 指定脚本文件,从脚本文件中读取awk命令 |
-F | 指定分隔符 |
-v | 自定义变量 |
(2)模式表示在数据中要查找的内容,通常由逻辑运算表达式组成
(3)操作表示要执行的一系列命令,常见的操作为一条print命令,也可以一段程序,操作由一对花括号括起来。
(4)内置变量
在awk命令中,除了前面介绍的位置变量,还会经常使用一些内置变量,常用的内置变量如下表所示
变量名 | 含义 |
NF | 每一行{$0}拥有的字段个数 |
NR | 已读取的行数,也就是当前正在处理的行号 |
FS | 指定分隔字符 |
FILENAME | 表示当前文件名 |
3、实例演示
在以下实例中,以处理/etc/passwd文件为例,该文件中的各字段用冒号间隔。
(1)打印指定字段
# 打印出第1列和第3列的值,文件中字段间用冒号间隔,输出时,各字段之间用一个Tab间隔
[root@node1 ~]# awk -F: '{ print $1 "\t" $3 }' /etc/passwd
root 0
bin 1
daemon 2
……此处省略其它输出……
(2)内置变量的应用
# 打印当前行号,文件名和指定字段名及其值
[root@node1 ~]# awk -F: '{ print NR "\t" FILENAME "\t" "username: "$1 "\t" "UID: "$3 }' /etc/passwd
1 /etc/passwd username: root UID: 0
2 /etc/passwd username: bin UID: 1
3 /etc/passwd username: daemon UID: 2
……此处省略其它输出……
注:在awk命令中,内置变量不需要使用$符号,但位置变量仍需要用$。
(3)模式过滤
awk 的 模式可以使用条件判断,比如只打印出uid值小于5的行,命令如下:
# 打印UID值不超过5的记录中的用户名和UID
[root@node1 ~]# awk -F: '$3 <= 5 { print $1 "\t" $3 }' /etc/passwd
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
(4)统计和计算
awk 还可以快速计算和统计,比如求和、最大值,最小值,平均值等。
# 统计用户数
[root@node1 ~]# awk 'BEGIN { sum=0 } { sum+=1 } END { print "total users:", sum }' /etc/passwd
total users: 36
# 统计文件中指定字段的最大值
[root@node1 ~]# awk -F: 'BEGIN { max=0 } { if($3>max) max=$3 } END { print "max uid:", max }' /etc/passwd
max uid: 65534
上面命令中的 BEGIN 和 END 都是awk的关键字:
- BEGIN:表示在awk程序开始前执行一次;
- END:表示在awk程序结束后执行一次。
(5)print和printf函数
awk同时支持 print 和 printf 两种打印输出的函数,它们的区别如下:
- print:其参数可以是变量、数值或字符串,字符串必须用双引号,参数用逗号分开;
- printf:其用法与C语言的printf相似,可以格式化输出。
# 计算uid的平均值,值的宽度为10个字符,其中小数点后保留2位
[root@node1 ~]# awk -F: 'BEGIN { sum=0 } { sum+=$3 } END { printf("uid average = %10.2f\n", sum/NR) }' /etc/passwd
uid average = 2253.64