sort 是文本處理瑞士軍刀,掌握其 -k 鍵值排序、-n 數值排序、-s 穩定排序、-t 分隔符,能秒級完成日志分析、數據清洗、報表生成。本文系統講解參數語法、-k 複雜鍵值定義、多級排序邏輯、實戰案例庫。
核心參數速查表
| 參數 | 長選項 | 作用 | 備註 |
-n | --numeric-sort | 按數值大小排序(非字典序) | 「10」大於「2」,避免字典序「10」<「2」 |
-r | --reverse | 逆序(降序) | 配合 -n 為數值降序 |
-u | --unique | 去重(輸出唯一行) | 類似 uniq 但自帶排序 |
-t | --field-separator=SEP | 指定列分隔符(單字符) | 默認「空白到非空白」過渡,-t, 為 CSV |
-k | --key=POS1[,POS2] | 指定排序鍵(起始/結束位置) | 核心進階參數,詳見下文 |
-s | --stable | 穩定排序(保持相等鍵的原始順序) | 禁用最後手段重排,多級排序必備 |
-f | --ignore-case | 忽略大小寫 | 字典序排序時有用 |
-b | --ignore-leading-blanks | 忽略行首空白 | 配合 -k 避免縮進干擾 |
-M | --month-sort | 按月份縮寫排序 (JAN| 日志月份排序神器 | |
-c | --check | 檢查是否已排序,否則報錯 | 腳本驗證用 |
-o | --output=FILE | 輸出到文件(可原地覆蓋) | 比重定向安全,支持輸入即輸出 |
-k 鍵值定義完整語法
-k FStart[.CStart][Modifier][,FEnd[.CEnd][Modifier]]
# FStart: 起始字段號(從 1 開始)
# CStart: 起始字符位置(從 1 開始,默認 1)
# Modifier: n/r/M/b 等單字段修飾符
# FEnd/CEnd: 結束字段/字符(默認行尾)
# 逗號前為起始,後為結束;省略結束則到行尾
經典 -k 用法示例
| 命令片段 | 含義 |
-k 2 | 按第 2 字段到行尾排序 |
-k 2,2 | 僅按第 2 字段排序 |
-k 2,2n | 按第 2 字段數值排序 |
-k 2.3,2.5 | 按第 2 字段第 3-5 字符排序 |
-k 2,2 -k 1,1 | 先按第 2 字段,再按第 1 字段(多級排序) |
-k 2,2nr -k 1,1 | 第 2 字段數值降序,再第 1 字段升序 |
實戰案例庫
樣本文件 name_list.txt
aName:aGender:aProfession:aBirthday:aHeight:aEtc.
Abbie Cornishi:female:actor:19820807:1.73m:Klondike
Hara Mikie:female:pictorial model:19870703:1.62m:Oscar Promotion
Drew Barrymore:female:actor:19750222:1.63m:Music and Lyrics
Kobe Bryant:male:NBA player:19780823:1.98m:Los Angeles Lakers
Timothy Theodore Duncan:male:NBA player:19760425:2.11m:San Antonio Spurs
Tony Parker:male:NBA player:19820517:1.88m:San Antonio Spurs
Manu Ginóbili:male:NBA player:19770728:1.98m:San Antonio Spurs
LaMarcus Aldridge:male:NBA player:19850719:2.11m:Portland Trail Blazers
aName:aGender:aProfession:aBirthday:aHeight:aEtc.
1. 基礎排序與去重
sort name_list.txt # 字典序升序
sort -u name_list.txt # 去重後字典序
sort -r name_list.txt # 字典序降序
sort -ru name_list.txt # 去重後降序
2. 按生日排序(字段 4,數值)
sort -t: -k 4,4n name_list.txt # 生日升序(最年長在前)
sort -t: -k 4,4nr name_list.txt # 生日降序(最年輕在前)
3. 按身高排序(字段 5,帶單位需預處理)
# 身高格式 1.73m,直接數值排序會把 m 當字符
# 方案:sed 移除 m 再排序,或用 -k 5.1,5.3n(假設固定格式 x.xx)
sort -t: -k 5.1,5.3n name_list.txt # 身高升序
4. 多級排序:性別 → 職業 → 生日
sort -t: -k 2,2 -k 3,3 -k 4,4n name_list.txt
# 先性別 (female
5. 穩定排序保證原始順序(關鍵)
# 無 -s 時,相等鍵可能被後續字段重排
sort -t: -k 2,2 -s name_list.txt # 僅按性別排序,同性別保持原文件順序
# 多級排序鏈式穩定排序等價:
sort -t: -k 4,4n -s name_list.txt | sort -t: -k 3,3 -s | sort -t: -k 2,2 -s
6. CSV 文件處理(含引號、逗號)
# 簡單 CSV(無引號逗號)
sort -t, -k 3,3n data.csv
# 複雜 CSV 建議用 csvkit: csvsort -c 3 data.csv
# 或 Python: python -c "import csv,sys; print(''.join(sorted(sys.stdin, key=lambda r: float(r.split(',')[2]))))"
7. 日志時間戳排序(ISO 8601 格式)
# 2023-10-01T12:34:56 格式可直接字典序排序
sort -k 1,1 access.log
# 非標準格式需提取關鍵字段
# [01/Oct/2023:12:34:56] → 用 -k 1.2,1.9M -k 1.10,1.11n -k 1.12,1.13n -k 1.14,1.15n
sort -k 1.2,1.9M -k 1.10,1.11n -k 1.12,1.13n -k 1.14,1.15n access.log
性能優化大文件排序
sort -S 50% -T /tmp/bigsort large.log:-S 內存緩衝(50% 物理內存),-T 臨時文件目錄(掛載大盤/SSD)。
sort --parallel=8 -S 2G large.log:多線程並行排序(GNU sort 8.8+)。
- 超大文件(>內存 10倍)考慮
split 分塊排序再 sort -m 歸併。
避坑指南
- 分隔符陷阱:
-t 僅支援單字符,多字符分隔符需 sed 's/::/|/g' 預處理。
- 數值排序陷阱:
-n 僅識別行首/字段首數字,1.73m 會被解析為 1.73,但 m 導致字符串比較異常,建議預處理純數值。
- 區域設置影響:
LC_ALL=C sort ... 強制 C 語言環境,避免多語言排序規則差異、大幅提速。
- 穩定排序必要性:多級排序鏈式管道時,每級必須加
-s,否則後級排序會打亂前級相等鍵的順序。