CLI AI

用 awk 打印 CSV 的某一列(以及何时不该用)

2026-05-06

awk -F, '{print $2}' file.csv 一行就能取出一列,对于程序生成的 CSV,这样就够了。但如果 CSV 来自电子表格,就有一个陷阱:它不会报错,只会悄悄给出错误的数字,所以有必要弄清楚这条界线在哪里。

1. 取一列

clai
$ clai 打印 data.csv 的第一列→ awk -F, '{print $1}' data.csvnameAliceBob

-F, 设置字段分隔符。字段是 $1、$2……$0 是整行。

2. 取多列,跳过表头

clai
$ clai 打印 data.csv 的第 1 和第 3 列,跳过表头行→ awk -F, 'NR>1 {print $1, $3}' data.csvAlice 100Bob 250

NR>1 跳过第一行。NR 是记录编号,把它当作条件正是 awk 表达“对于……的行”的方式。

3. 输出时保持逗号分隔

clai
$ clai 把第 1 和第 3 列提取为合法的 csv→ awk -F, 'BEGIN{OFS=","} NR>1 {print $1,$3}' data.csvAlice,100Bob,250

print $1, $3 用 OFS 拼接字段,它默认是空格。在 BEGIN 里设置它,输出就又是 CSV 了。

4. 对某一列求和

clai
$ clai 统计 data.csv 第三列的总和→ awk -F, 'NR>1 {s+=$3} END {print "total", s}' data.csvtotal 350

不用声明变量,也不用初始化——awk 里的数字默认从零开始。END 在最后一行处理完后只执行一次。

5. 先过滤行,再取一列

clai
$ clai 显示金额超过 200 的名字→ awk -F, 'NR>1 && $3 > 200 {print $1}' data.csvBob

这正是 awk 胜过电子表格的地方:同一条命令可以扫过一个 3 GB 的文件,而不用把它打开。

6. 陷阱:引号内的逗号

clai
$ clai 打印第二列→ awk -F, 'NR>1 {print $2}' data.csvBerlin"Paris

Bob,"Paris, France",250 这一行逻辑上是三个字段,却有四个逗号。Awk 根本不知道引号是什么,于是 $2 变成了 "Paris,$3 变成了 France",第 4 步的求和也就悄悄从 350 变成了 100。它不会报错——只会给你一个错误的数字。

常见坑

  • 在相信总和之前先检查引号。 grep -c '"' file.csv ——如果结果是零,普通 awk 就是安全的。如果不是,就用真正的 CSV 解析器:csvcut -c 1,3 data.csv(csvkit)、mlr --csv cut -f name,amount(Miller),或者三行 Python 代码。
  • -F, 不等于 -F', '。 「逗号加空格」这种分隔符会在没有那个空格的行里悄悄产生空字段。
  • Windows 换行符会在最后一个字段留下 \r。 这会让 $NF 的比较莫名其妙地失败。可以用 awk -F, '{gsub(/\r$/,"")} …' 修复,或者先跑一遍 dos2unix。

相关问题

怎么打印最后一列? awk -F, '{print $NF}'。NF 是字段数,所以 $NF 是最后一个,$(NF-1) 是倒数第二个。

怎么用制表符做分隔符? awk -F'\t' ——记得加引号,不然 shell 会吃掉反斜杠。

这种场景 awk 比 pandas 快吗? 对于从大文件里提取或求和一列,是的,快很多——它是流式处理,不会构建任何数据结构。涉及 join 或重塑数据时,还是用 pandas。

相关阅读

描述你想要提取的内容,CliAI 会帮你写好 awk 程序,连你容易忘记的 BEGIN{OFS=","} 也一并写上。一行命令安装。