前言

awk 不仅仅是一个简单的命令:它是一种成熟的语言,可以实现非常酷的功能!

awk 的用例包括:

  • 文本处理
  • 格式化文本报告
  • 执行数学运算
  • 执行字符串操作

文件准备

将下面内容保存为tools.csv

name,price,quantity
drill,99,5
hammer,10,50
brush,5,100
lamp,25,30
brush,5,100
screwdriver,5,23
table-saw,1099,3

准备工作完毕,现在开始下面的内容!

使用awk

awk的最基本功能就是打印一个文件:

$ awk '{ print }' tools.csv

这里的{ print }是main block,我们还可以有BEGIN block和END block,通过定义header可以定义这样的block:

$ awk 'BEGIN { print "tools.csv" } { print NR, $0 } END { print NR }' tools.csv
tools.csv
1 name,price,quantity
2 drill,99,5
3 hammer,10,50
4 brush,5,100
5 lamp,25,30
6 brush,5,100
7 screwdriver,5,23
8 table-saw,1099,3
8

这的NR代表的是行号,$0代表这一行全部内容。

awk还能实现更多强大的功能:

我们可以只选择含有brush的行进行打印输出:

$ awk '/brush/' tools.csv
brush,5,100
brush,5,100

然后,我们可以只打印它们的第2列和第3列(awk列数从1开始):

$ awk -F, '/brush/ { print $2 "\t" $3 }' tools.csv
5       100
5       100

这里-F,的意思是使用逗号作为定界符号。或者,如果我们只想打印第3行,那么可以使用:

$ awk -F, 'NR == 3' tools.csv

如果希望基于某一字段进行筛选,那么可以使用:

# 筛选第二列为5的行
$ awk -F, '$2 == 5 { print NR, $0 }' tools.csv
# 筛选第一列为brush的行
$ awk -F, '$1 == "brush" { print NR, $0 }' tools.csv

我们还可以串联这些表达式:

$ awk -F, '$2 == 5 && $3 < 100 { print NR, $0 }' tools.csv

我们可以对第3列求和,求出所有工具的数量:

# 求出所有工具的数量
$ awk -F, '{ x+=$3 } END { print x }' tools.csv
# 求出所有brush的数量
$ awk -F, '$1 == "brush" { x+=$3 } END { print x }' tools.csv

可以打印文件的行数和列数:

awk -F, 'BEGIN { print "COLUMNS", "ROWS" }; END { print NF, NR }' tools.csv

打印重重出现2次的行:

awk -F, '++seen[$0] == 2' tools.csv

合并两个csv文件可以这样命令:

$ cp tools.csv tools2.csv
$ awk 'FNR==1 && NR!=1{next;}{print}' *.csv > tools3.csv

对于行数很多的文件,可以这样分割成多个小文件:

$ sed '1d' tools3.csv | awk 'NR%7==1 {x="data"++i".csv"} {print > x}'
$ ls | grep data

最后,展示一个实际应用,可以使用下面的命令得到eth0接口的硬件地址,其中toupper函数可以将字母改为大写然后输出:

ifconfig eth0 | awk -F":" '/HWaddr/{print toupper($3 $4 $5 $6 $7)}'

参考链接