awk命令可实现Linux文本列的精细化处理:一、用-F指定分隔符提取列;二、结合正则条件筛选后输出;三、用正则FS或match/substr处理复杂字段;四、对列值进行算术运算与printf格式化;五、利用NR、RS等变量处理跨行数据。

如果您需要在Linux系统中对文本文件的列进行精细化处理,尤其是提取特定列并结合条件筛选、格式化或计算,awk命令提供了强大而灵活的进阶能力。以下是实现此类操作的具体方法:
一、使用awk按字段分隔符提取指定列
awk默认以空白字符(空格或制表符)为分隔符,通过$N可直接引用第N列。当文本使用非默认分隔符(如冒号、逗号、竖线)时,需显式指定-F选项。
1、提取/etc/passwd文件中用户名(第1列)和用户ID(第3列),以冒号为分隔符:
awk -F ':' '{print $1, $3}' /etc/passwd
2、提取CSV文件中第2列和第4列,以英文逗号为分隔符:
awk -F ',' '{print $2, $4}' data.csv
3、提取以竖线分隔的日志片段中第5列(响应状态码)和第8列(字节数):
awk -F '|' '{print $5, $8}' access.log
二、结合正则匹配条件筛选后提取列
awk支持在打印前对整行或某列执行模式匹配,仅对满足条件的记录执行列提取操作,避免冗余输出。
1、从netstat输出中提取所有处于ESTABLISHED状态的连接,并只显示本地端口(第4列)和远程地址(第5列):
netstat -tn | awk '$6 == "ESTABLISHED" {print $4, $5}'
2、从ps输出中筛选包含"nginx"的进程,提取PID(第2列)和命令名(第11列):
ps aux | awk '$11 ~ /nginx/ {print $2, $11}'
3、提取/etc/fstab中非注释、非空行的第1列(设备路径)和第2列(挂载点),跳过以#开头或全空白的行:
awk '!/^$/ && !/^\\s*#/ {print $1, $2}' /etc/fstab
三、使用自定义字段分隔符与动态列定位
当字段内容本身包含空格但逻辑上属于同一列(如日志中的带空格时间戳),可借助正则表达式定义FS,或用match()函数配合substr()精确定位。
1、将Apache日志中双引号包裹的User-Agent字段(通常为第12列)完整提取,避免被内部空格错误切分:
awk -F '"[^"]*"|\s+' '{print }' access.log
2、使用正则FS匹配多个连续空白作为分隔符,确保多空格对齐的列不被误判:
awk -F '\\s+' '{print $1, $NF}' aligned_data.txt
3、先用match()定位引号内起始位置,再用substr()截取完整字段:
awk '{start = match($0, /"([^"]*)"/); if (start) print substr($0, RSTART+1, RLENGTH-2)}' access.log
四、对提取列执行算术运算与格式化输出
awk内置变量和运算符支持对列值进行加减乘除、计数、求和、平均等操作,并可用printf实现对齐、补零、单位转换等格式控制。
1、统计系统中各用户启动的进程数,对第1列(USER)计数并排序:
ps -eo user= | awk '{count[$1]++} END {for (u in count) print u, count[u]}' | sort -k2,2nr
2、提取df输出中已用空间(第5列,含%符号),去除%并计算数值大于85的文件系统:
df | awk '$5 ~ /%$/ {sub(/%/, "", $5); if ($5 > 85) print $1, $5"%"}'
3、对日志中第10列(响应时间毫秒)求总和、均值与最大值:
awk '{sum += $10; if ($10 > max) max = $10; cnt++} END {printf "Sum: %d, Avg: %.2f, Max: %d\n", sum, sum/cnt, max}' access.log
五、多行合并与跨行字段关联提取
利用awk的NR(总行号)、FNR(当前文件行号)、RS(输入记录分隔符)和ORS(输出记录分隔符)变量,可处理跨物理行逻辑上属于同一记录的文本,例如邮件头、JSON块或分段日志。
1、将邮件头中Subject和From字段合并为单行输出,以空行分隔不同邮件:
awk '/^Subject:/ {sub(/^Subject: */, ""); subj = $0; next} /^From:/ {sub(/^From: */, ""); print subj "\t" $0}' mail.txt
2、将多行JSON对象(每对象占多行)按字段提取:先设RS为空行,再用gsub()清理换行后解析:
awk 'BEGIN{RS=""} {gsub(/\n/, " ", $0); if ($0 ~ /"name":/) print $0}' json_blocks.txt
3、提取top命令动态输出中CPU使用率最高进程的命令名(第12列)和占用率(第9列),需跳过标题行:
top -bn1 | awk 'NR > 7 {if ($9 > max) {max = $9; cmd = $12}} END {print cmd, max}'










