awk 文本处理

awk 是一个强大的文本处理语言,得名于三位作者 Aho、Weinberger、Kernighan 的姓氏首字母。它不仅能按列处理数据,还支持变量、条件判断、循环、函数,是数据分析和报表生成的利器。

基本语法

awk '模式 {动作}' 文件
awk -F 分隔符 '模式 {动作}' 文件

awk 默认按空格或制表符分割字段,-F 可以指定分隔符。

字段变量

awk 自动将每行分割成字段,用 $1$2$3 等访问:

变量含义
$0整行内容
$1第1个字段
$2第2个字段
$NF最后一个字段
NF字段数量
NR当前行号
echo "张三 25 北京" | awk '{print $1, $3}'
awk '{print NR, $0}' file.txt
awk '{print $1, $NF}' data.txt

指定分隔符

awk -F: '{print $1}' /etc/passwd
awk -F, '{print $1, $3}' data.csv
awk -F'\t' '{print $1}' data.tsv

模式匹配

行号匹配

awk 'NR==1' file.txt
awk 'NR<=5' file.txt
awk 'NR%2==0' file.txt

分别输出:第1行、前5行、偶数行。

正则匹配

awk '/error/' app.log
awk '/^root/' /etc/passwd
awk '$3 > 100' data.txt

条件表达式

awk '$3 > 50 {print $1, $3}' scores.txt
awk '$NF == "error" {print $0}' app.log
awk '$2 >= 60 && $2 < 80 {print $1, "及格"}' scores.txt

内置变量

变量含义
FS输入字段分隔符
OFS输出字段分隔符
RS输入记录分隔符
ORS输出记录分隔符
FILENAME当前文件名
FNR当前文件的行号
awk 'BEGIN{FS=":"; OFS="-"} {print $1, $3}' /etc/passwd
awk '{print FILENAME, NR, $0}' *.txt

BEGIN 和 END

BEGIN 在处理前执行,END 在处理后执行:

awk 'BEGIN{print "姓名\t分数"} {print $1"\t"$2} END{print "处理完成"}' scores.txt

统计总和和平均值:

awk '{sum+=$2} END{print "总分:", sum, "平均:", sum/NR}' scores.txt

统计行数:

awk 'END{print NR}' file.txt

流程控制

if 语句

awk '{
    if ($3 >= 90) 
        print $1, "优秀"
    else if ($3 >= 60) 
        print $1, "及格"
    else 
        print $1, "不及格"
}' scores.txt

for 循环

awk '{
    for (i=1; i<=NF; i++) {
        print $i
    }
}' file.txt

while 循环

awk '{
    i = 1
    while (i <= NF) {
        print $i
        i++
    }
}' file.txt

数组

awk 支持关联数组:

awk '{
    count[$1]++
} END {
    for (name in count) {
        print name, count[name]
    }
}' access.log

统计每个 IP 的访问次数。

内置函数

字符串函数

awk '{print length($0)}' file.txt
awk '{print substr($1, 1, 3)}' file.txt
awk '{print toupper($1)}' file.txt
awk '{print tolower($1)}' file.txt
awk '{print split($0, arr, ":")}' file.txt

数学函数

awk '{print int($1)}' file.txt
awk '{print sqrt($1)}' file.txt
awk 'BEGIN{print rand()}'

实用示例

提取特定列

awk '{print $1, $5}' access.log
awk -F: '{print $1}' /etc/passwd

计算列的总和

awk '{sum+=$3} END{print sum}' data.txt

按条件过滤

awk '$3 > 1000 {print $0}' data.txt
awk '$4 == "error" {print $0}' app.log

格式化输出

awk '{printf "%-10s %5d\n", $1, $2}' data.txt

统计访问量前10的IP

awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10

或者纯 awk:

awk '{count[$1]++} END {for (ip in count) print count[ip], ip}' access.log | sort -rn | head -10

合并两个文件

awk 'NR==FNR{a[$1]=$2; next} {print $0, a[$1]}' file1 file2

小结

  • awk 是强大的文本处理语言,支持字段操作和编程特性
  • $1$2 访问字段,$0 是整行,$NF 是最后字段
  • -F 指定分隔符
  • BEGIN 和 END 用于预处理和后处理
  • 支持数组、条件、循环、函数
  • 适合数据分析和报表生成