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 在处理后执行:
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
awk '{
if ($3 >= 90)
print $1, "优秀"
else if ($3 >= 60)
print $1, "及格"
else
print $1, "不及格"
}' scores.txt
awk '{
for (i=1; i<=NF; i++) {
print $i
}
}' file.txt
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
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
$1、$2 访问字段,$0 是整行,$NF 是最后字段-F 指定分隔符