【Shell】Linux 文本按指定列排序:sort 与 awk 高效实战

admin / Shell / / 1236 字 · 约 6 分钟 / 643 次阅读 /

在 Linux 文本处理与日志分析场景中,我们经常遇到类似 Nginx 访问日志、API 监控打点等由空格或特定字符分隔的结构化数据。最常见的需求是:提取其中某一列数值(如耗时、请求体大小、响应码频次),按照数值大小进行升序或降序排列,并完整打印匹配的整行内容

本文以实际日志片段为例,深度解析 sort 的列排序参数核心技巧,并对比 sort 单独处理与 awk + sort 组合流的高效解法。


一、方案速查与核心参数对比

在对包含多列的文件进行排序时,sort 提供了非常精细的列选择和排序行为控制参数:

参数 全称与功能 典型示例 注意事项
-t 指定列字段分隔符 (默认为空格/制表符连续空白) -t ' '-t ':' 多个连续空格时注意与默认空白行为的区别
-k 指定排序字段区间 [起始列,终止列] -k 3,3 强烈建议写成 3,3,避免跨列比较导致逻辑偏差
-n 按通用数值大小比较 (Numeric Sort) -k 3,3n 不加 -n 会按 ASCII 字典序排序(如 21 会排在 3 前面)
-r 倒序/逆序排列 (Reverse) -k 3,3nr 由大到小降序输出

[!WARNING] 使用 sort -k 的经典避坑点: 如果只写 -k 3sort 会将从第 3 列一直到行尾的所有内容当成一个整体参与排序比较!正确的写法必须显式限定单列范围:-k 3,3


二、实战演练:按指定数值列降序排序

1. 示例数据集 data.txt

假设我们有一组 API 网关请求记录文件 data.txt(包含请求方式、路径、耗时毫秒数、客户端 IP):

GET //api/ 12 100.122.183.158
GET //api/ 11 100.122.183.158
GET //api/ 21 100.122.183.158
GET //api/ 23 100.122.183.158
GET //api/ 2 100.122.183.158
GET //api/ 26 100.122.183.158
GET //api/ 22 100.122.183.158

2. 推荐方案:原生 sort 单命令一行搞定

如果数据格式本身规整,推荐直接使用原生 sort 工具,无需额外启动多级管道,执行效率最高:

# 需求:按照第 3 列(耗时)数值大小由大到小(降序)排列整个数据行
sort -t ' ' -k 3,3nr data.txt

输出结果

GET //api/ 26 100.122.183.158
GET //api/ 23 100.122.183.158
GET //api/ 22 100.122.183.158
GET //api/ 21 100.122.183.158
GET //api/ 12 100.122.183.158
GET //api/ 11 100.122.183.158
GET //api/ 2 100.122.183.158

[!TIP] 可以看到耗时为 2 的记录被正确排在了最后,这是 -n 数值模式生效的关键。如果遗漏了 -n,字符串 2 会错误地排在 1211 的前面。


3. 进阶场景:awk + sort 组合流处理复杂衍生列

当排序列需要动态计算(例如第 3 列除以第 4 列的衍生比率),或者需要先清洗再排序时,可以利用 awk 提取行号与目标排序列,再回查原行:

# 方案:提取行号与目标列 -> 按计算值降序 -> 逐行恢复原始输出
for line_num in $(awk '{print NR, $3}' data.txt | sort -rn -k2,2 | awk '{print $1}')
do
    awk "NR == $line_num" data.txt
done

或者使用更加高效的单管道流(避免 for 循环反复 fork 进程):

# 将计算值作为第一列临时附加 -> 排序 -> 剥离临时列恢复原貌
awk '{print $3, $0}' data.txt | sort -rn -k 1,1 | cut -d ' ' -f 2-

三、总结与最佳实践

  1. 常规按列排序:优先使用 sort -t ' ' -k N,Nnr file.txt,简洁且性能最优;
  2. 切记闭合字段区间:字段定位始终采用 -k N,N 形式,防止列跨越;
  3. 复杂计算列:借助 awk '{print calc_val, $0}' | sort ... | cut 这种附加列再剥离的经典流水线设计模式,兼顾灵活性与高执行效率。
admin

admin

云原生架构 · 全栈开发

感谢阅读本文!记录系统架构思考与实战复盘。专注于 Python、Django、PostgreSQL 与云原生容器化工程实践。