使用awk在终端处理数据
前言
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)}'