由于这些年 Python 和机器学习的流行,一说到 CSV 文件,马上想到的工具是 pandas。pandas 很好,但是很多简单的处理,用一个更轻量的工具可以实现,而且几乎所有的 Unix/Linux 系统都附带了这工具(当然也包括 macOS)。这就是 awk。我这篇要谈的是 awk 的几个使用例子。
假设有一个文件 bangumi.csv
内容如下:
日期 番名 更新集数 播放(万)
周一 书店里的骷髅店员本田 第5话 242.6
周二 关于我转生变成史莱姆这档事 第6话 2438.7
周三 强风吹拂 第6话 207.6
周四 青春猪头少年不会梦到兔女郎学姐 第6话 1847.9
周五 魔法禁书目录-第三季 第5话 1291.9
周六 JOJO的奇妙冒险-黄金之风 第5话 851.7
周日 刀剑神域-Alicization 第5话 2170.1
以下的各个例子都是对这个文件的处理。
一、输出某些列
例1
只想要番名那一列,可以这样用。
awk '{print $2}' bangumi.csv
结果:
番名
书店里的骷髅店员本田
关于我转生变成史莱姆这档事
强风吹拂
青春猪头少年不会梦到兔女郎学姐
魔法禁书目录-第三季
JOJO的奇妙冒险-黄金之风
刀剑神域-Alicization
注意点:
- awk 默认用空格或
\t
来分隔列。列分隔符可以用-F
选项来指定。 - 列从 1 开始计数,
$1
表示第一列,$NF
表示最后一列,$(NF-1)
表示倒数第二列,$0
表示整行。
例2
想要番名和日期那两列,并且调换下顺序,用,
分隔,并且标出行号。
awk '{print NR ". " $2 "," $1}' bangumi.csv
结果:
1. 番名,日期
2. 书店里的骷髅店员本田,周一
3. 关于我转生变成史莱姆这档事,周二
4. 强风吹拂,周三
5. 青春猪头少年不会梦到兔女郎学姐,周四
6. 魔法禁书目录-第三季,周五
7. JOJO的奇妙冒险-黄金之风,周六
8. 刀剑神域-Alicization,周日
注意点:
- 双引号内的内容会原样输出。
- 变量 NR 表示行号。
二、输出某些行
例3
例2 中的结果包含了表头,这里修正一下,把表头去掉,只留下内容。
awk 'NR > 1 {print NR - 1 ". " $2 "," $1}' bangumi.csv
结果:
1. 书店里的骷髅店员本田,周一
2. 关于我转生变成史莱姆这档事,周二
3. 强风吹拂,周三
4. 青春猪头少年不会梦到兔女郎学姐,周四
5. 魔法禁书目录-第三季,周五
6. JOJO的奇妙冒险-黄金之风,周六
7. 刀剑神域-Alicization,周日
注意点:
- 加在大扩号前面的是对行的过滤条件。
- 因为输出少了一行,
NR - 1
修正一下行号。
例4
输出更新到第5话的日期和番名。
awk '/第5话/ {print $1,$2}' bangumi.csv
结果:
周一 书店里的骷髅店员本田
周五 魔法禁书目录-第三季
周六 JOJO的奇妙冒险-黄金之风
周日 刀剑神域-Alicization
注意点:
- 行过滤条件可以用正则表达式
- 正则表达式要写在一对
/
中间
三、统计
例5
在例4 的基础上,多输出一个行号。
错误示范:如果用 NR
输出行号,结果会是
# awk '/第5话/ {print NR ". " $1,$2}' bangumi.csv
2. 周一 书店里的骷髅店员本田
6. 周五 魔法禁书目录-第三季
7. 周六 JOJO的奇妙冒险-黄金之风
8. 周日 刀剑神域-Alicization
正确的做法是用一个变量来计数:
awk '/第5话/ {n+=1; print n ". " $1,$2}' bangumi.csv
结果:
1. 周一 书店里的骷髅店员本田
2. 周五 魔法禁书目录-第三季
3. 周六 JOJO的奇妙冒险-黄金之风
4. 周日 刀剑神域-Alicization
注意点:
- 用
;
分隔多个动作。 - 变量初始值默认为空,空值用来计算的话,当0来处理。
例6
让例5 中的行号,从零开始。
awk 'BEGIN {n=-1} /第5话/ {n+=1; print n ". " $1,$2}' bangumi.csv
结果:
0. 周一 书店里的骷髅店员本田
1. 周五 魔法禁书目录-第三季
2. 周六 JOJO的奇妙冒险-黄金之风
3. 周日 刀剑神域-Alicization
注意点:
-
BEGIN
的内容只在最开始的时候执行一次。
例7
把所有番剧的播放量累加一下,附在最后。
awk '{if (NR>1) s+=$4; print $0} END{print "----------------"; print "总播放量: " s "万"}' bangumi.csv
结果:
日期 番名 更新集数 播放(万)
周一 书店里的骷髅店员本田 第5话 242.6
周二 关于我转生变成史莱姆这档事 第6话 2438.7
周三 强风吹拂 第6话 207.6
周四 青春猪头少年不会梦到兔女郎学姐 第6话 1847.9
周五 魔法禁书目录-第三季 第5话 1291.9
周六 JOJO的奇妙冒险-黄金之风 第5话 851.7
周日 刀剑神域-Alicization 第5话 2170.1
----------------
总播放量: 9050.5万
注意点:
- 利用
if ()
语句可以做细致的过滤。 -
END
的内容只在前面的动作执行完之后执行一次。
如果想更多得了解「变量」「动作」等概念,可以参考一下阮一峰的这篇博客 awk 入门教程
网友评论