awk - 简介

awk指令的名称来自它的三位作者的姓名缩写:Alfred Aho, Peter Weinberger 和 Brian Kernighan。

它的主要行为就是:以行为单位进行分析、处理,特别适合处理文本格式的文件。

awk - 指令格式

$ awk 'pattern {action}' file
                                    

在单引号中的pattern和action,分别表示条件判断和执行的指令,file是待处理的文件。

当然,也可以使用管道的形式为awk指令提供处理数据,或者是来自用户的终端输入,就像sed指令中描述的那样。

pattern条件判断包括:

  • == 相等
  • != 不相等
  • > 大于
  • >= 大于或等于
  • < 小于
  • <= 小于后等于
  • && 逻辑与
  • || 逻辑或

另外,pattern还支持正则表达式。

action指令部分,最常用的就是print,用来输出相应的栏位。

awk内部提供了一些常用的内建变量,可以用来辅助输出一些有用的信息,常用的有:

  • NR 读取到的行号;
  • NF 当前处理行的栏位数(列数);
  • FS 输入分隔符,默认:空格;
  • OFS 输出分隔符,默认:空格;
  • FILENAME 输入文件名
awk - 打印列

awk默认以空格来分隔一行内容,被分割的每一块内容以$n的变量形式表示,其中$0表示整行内容。

例如:打印文件中第1列和第3列


// 测试文件
$ cat test.txt
ZhangSan     male      30     student
LiSi         male      40
WangWu       male      50     worker
$
$ awk '{print $1,$3}' test.txt
ZhangSan 30
LiSi 40
WangWu 50
                                    

为了让输出信息更直观,可以在指令中添加额外的字符串,例如:


$ awk '{print "col-1="$1," col-3="$3}' test.txt
col-1=ZhangSan  col-3=30
col-1=LiSi  col-3=40
col-1=WangWu  col-3=50
                                    

示例:打印每一行的行号,以及该行有多少列


$ awk '{print "line="NR ", col=" NF "\t" $0}' test.txt
line=1, col=4	ZhangSan     male      30     student
line=2, col=3	LiSi         male      40
line=3, col=4	WangWu       male      50     worker
                                    

示例:打印倒数第 1 列和倒数第 2 列


$ awk '{print $(NF-1) "===" $NF}' test.txt
30===student
male===40
50===worker
                                    
awk - BEGIN 和 END

[BEGIN] {初始化语句}
[{awk 命令}]
[END{最后执行的语句}]
                                    

以上这 3 部分内容不需要同时存在。

如果存在的话,BEGIN和END只会执行一次,用来做一些初始化(例如:设置分隔符)和统计信息(例如:统计处理了多少行)。

示例:设置输入分隔符,输出分隔符


// 测试文件
$ cat test2.txt
ZhangSan,male,30,student
LiSi,male,40
WangWu,male,50,worker
$
$ awk 'BEGIN{FS=",";OFS="==="} {print $1,$2} END{print "filename=" FILENAME ", rows="NR}' test2.txt
ZhangSan===male
LiSi===male
WangWu===male
filename=test2.txt, rows=3
                                    
awk - 对内容进行过滤

示例:打印第一列等于ZhangSan的那些行


$ awk '$1 == "ZhangSan" {print $0}' test.txt
ZhangSan     male      30     student
                                    

示例:打印行内容中包含 ang 的信息(正则表达式)


$ awk '/ang/ {print $0}' test.txt
ZhangSan     male      30     student
WangWu       male      50     worker
                                    

示例:打印行内人中以 W 开头的信息(正则表达式)

  • ^ 匹配开头字符
  • $ 匹配结束字符

$ awk '/^W/ {print $0}' test.txt
WangWu       male      50     worker
                                    

示例:打印行内容中包含Zhang或者Wang的信息

  • [] 匹配方括号中的任意字符

$ awk '/[Zh|W]ang/ {print $0}' test.txt
ZhangSan     male      30     student
WangWu       male      50     worker
                                    

示例:打印行内容中不包含Zhang和Wang的信息


$ awk '!/[Zh|W]ang/ {print $0}' test.txt
LiSi         male      40
                                    

示例:打印年龄小于45的信息


$ awk '$3<45 {print $0}' test.txt
ZhangSan     male      30     student
LiSi         male      40
                                    

示例:打印第4列不为空的信息


$ awk 'NF==4 {print $0}' test.txt
ZhangSan     male      30     student
WangWu       male      50     worker
                                    
awk - 格式化输出

格式化控制字符与 C 语言中的相同。

示例:格式化打印姓名和年龄


$ awk '{printf ("%10s %03d \n", $1, $3)}' test.txt
ZhangSan 030
LiSi 040
WangWu 050
                                    
Card image cap
Linux 茶馆
Card image cap
物联网小镇