awk通过-F指定分隔符、模式前置过滤、printf格式化,可高效提取并排版复杂文本字段,如/etc/passwd用户名与shell、Nginx日志字段、CSV简单解析等。

提取复杂文本中的特定列并格式化输出,关键在于准确识别字段边界、灵活筛选条件、控制输出样式。awk 的“模式-动作”结构天然适合这类任务,不需要额外安装工具,一行命令就能完成从解析到排版的全过程。
按非默认分隔符精准定位列
很多日志或导出数据使用冒号、竖线、逗号甚至多个空格分隔,不能依赖默认空格切分。必须用 -F 显式指定分隔符,否则列序会错乱。
-
冒号文件(如 /etc/passwd):
awk -F ':' '{print $1, $7}' /etc/passwd提取用户名和登录 shell -
竖线日志(如 Nginx access.log):
awk -F '\|' '{print $5, $8}' access.log注意竖线是正则元字符,需双转义 -
逗号 CSV(含引号嵌套时慎用):简单场景可用
awk -F ',' '{print $2, $4}' data.csv;复杂 CSV 推荐用 csvkit 或 Python,awk 不原生支持引号逃逸
用正则或数值条件过滤后再取列
直接打印所有行容易混入噪声,先筛再提更高效。条件写在 {} 前面,不满足就不执行 print。
- 匹配状态字段:
netstat -tn | awk '$6 ~ /^ESTABLISHED$/ {print $4, $5}'—— 第6列严格等于 ESTABLISHED 才输出本地端口和远程地址 - 数值范围筛选:
awk '$3 >= 1000 && $3 - 跳过注释与空行:
awk 'NF > 0 && !/^#/ {print $1, $2}' /etc/fstab—— NF 表示当前行字段数,为 0 即空行
用 printf 精确控制输出格式
print 只做简单拼接,printf 才能对齐、补零、保留小数、加单位,适合生成报表。
- 左对齐用户名(宽度12)、右对齐 UID(宽度6):
awk -F ':' '{printf "%-12s %6d ", $1, $3}' /etc/passwd - HTTP 日志中格式化响应时间(毫秒)和状态码:
awk '{printf "Status: %3s | Time: %4.1f ms ", $9, $NF}' access.log(假设最后一列是耗时) - 添加表头与分隔线:
awk 'BEGIN{printf "%-10s %-8s %-6s ", "Name","Age","Score"; printf "%-10s %-8s %-6s ", "----","---","-----"} {printf "%-10s %-8s %-6s ", $1,$2,$3}' data.txt
处理字段内嵌结构或动态分隔
当某列本身含分隔符(比如 JSON 片段、路径、带空格的用户名),单纯靠 -F 不够,需结合 substr、match 或重设 FS。
- 从第4列(如
/var/log/nginx/error.log)提取文件名:awk '{n=split($4,a,"/"); print a[n]}' logs.txt - 用正则提取 IP 地址(假设在第1列中):
awk '$1 ~ /[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/ {match($1, /[0-9]{1,3}(.[0-9]{1,3}){3}/); print substr($1, RSTART, RLENGTH)}' netstat.out - 把制表符分隔的输入,改为冒号输出:
awk 'BEGIN{FS=" "; OFS=":"} {print $1,$2,$5}' input.tsv

















