sort默认按ASCII码逐字符比较排序,故“10”排在“2”前;需用-n按数值排序、-k指定列、-t设置分隔符等参数明确排序依据。

sort 命令默认按字典序逐行排序,但直接用它处理数字、多列或带空格的数据,大概率会得到错误结果——比如把 10 排在 2 前面,或者按错列排序。关键不是“能不能排”,而是“怎么告诉它你真正想按什么排”。
为什么 sort 默认排序结果看起来很怪?
因为它是按 ASCII 码从左到右逐字符比的,不是按数值大小。例如:
100 2 15
默认排序输出是 100、15、2(因为首字符 1 2,而 100 和 15 都以 1 开头,继续比第二位 0 5)。
- 要按数字大小排,必须加
-n;不加就永远是字符串比较 - 如果数据含前导空格,
sort会把空格也当有效字符比,导致排序偏移——此时加-b忽略开头空白 - 大小写敏感:大写字母(A–Z)ASCII 值小于小写(a–z),所以
Zoo会排在apple前面;需要统一大小写时加-f
按某一列排序,-k 和 -t 必须配对用
比如 CSV 文件 data.csv 内容为:
apple,12,red banana,5,green cherry,100,yellow
想按第二列数字升序排,命令是:
sort -t',' -nk 2 data.csv
注意点:
-
-t','明确指定逗号为分隔符;不指定就按任意空白(空格/Tab)切,容易切歪 -
-k 2表示“从第 2 字段开始”,默认到行尾;如果只想比第 2 字段本身(避免受第 3 字段影响),应写-k 2,2 -
-n必须紧跟在-k前或后(如-nk 2或-k 2n),否则数值字段仍被当字符串比 - 若字段含空格(如
"John Doe",45,"NY"),sort无法自动识别引号包裹,需先用awk或csvkit清洗
去重必须先排序,-u 不是万能的
sort -u 看似简单,但它只保留“排序后相邻重复行中的第一行”。如果原始文件没排过序,-u 会漏掉大量重复。
- 正确流程永远是:
sort file | uniq或直接sort -u file(sort -u内部已隐含排序) - 但
-u判重是整行比,如果只想按某列去重(如日志里按 IP 去重),得先sort -k1,1再uniq -w N或配合awk '!seen[$1]++' -
sort -u和sort | uniq在行为上等价,但前者少一次管道开销;不过若后续还要用uniq -c统计频次,必须用后者
大文件或特殊格式,别硬扛默认行为
当处理 du -h 输出(如 1.2G、512K)或版本号(2.10.3 vs 2.9.1)时,-n 完全失效。
- 人类可读大小:用
-h,例如du -sh * | sort -hr(-h识别 K/M/G,-r逆序) - 版本号:用
-V,printf '%s\n' 1.9 1.10 2.0 | sort -V输出才是正确顺序 - 内存不足时,
sort会自动用/tmp做临时文件;若磁盘满或权限不足,会报sort: write failed: /tmp/sortXXXXXX: No space left on device—— 可用export TMPDIR=/path/to/bigger/disk切换临时目录 - 检查文件是否已排序(用于脚本断言):用
sort -c file,合法返回 0,未排序返回 1 并报错
最常被忽略的是字段边界和排序稳定性:-k 2 实际包含从第 2 字段起的所有内容,而真实需求往往只是“仅按第 2 字段值决定顺序”,这时候 -k 2,2 才是安全写法。另外,sort 默认不稳定(相同键的行相对顺序可能变),如需保持原序,得加 --stable(较新 GNU 版本支持)。


















