拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Linux sort命令详解:从基础排序到实战技巧,掌握文本处理核心

很高兴和你聊聊 Linux 系统中一个非常常用、看似简单但实则细节丰富的命令sort。很多朋友在初学 Linux 时可能只把它当作一个“把文本排个序”的小工具但在实际的日志分析、数据处理、脚本编写和运维工作中sort的威力远不止于此。本文我将带你从头梳理sort命令的核心用法、高级参数、常见坑点和实战技巧希望在你看完这篇文章之后再遇到排序需求时脑海中浮现的不再是“管道后面接 sort”这句简单的口头禅而是一套清晰完整的处理思路。1. 背景与核心概念1.1 什么是 sort 命令在 Linux/Unix 系统中sort是一个标准的文本排序工具。它的核心职责是读取标准输入或指定文件中的数据按照指定的排序规则如字典序、数值大小、月份顺序、逆序等进行排序并将结果输出到标准输出。简单来说它就是一条“生产线”原料是杂乱无章的文本行经过sort这条流水线的处理后输出的是一列井井有条的文本行。# 最简单的使用示例 cat /tmp/fruits.txt EOF banana apple cherry date EOF sort /tmp/fruits.txt输出结果为apple banana cherry date这里使用的是默认的“字典序”排序也叫按字符编码顺序排序默认从小到大升序。1.2 它解决了什么问题在没有sort命令的系统中如果我们想要对文本排序通常需要借助编程语言编写一段排序算法这非常繁琐。而sort的出现让运维人员、开发者和数据分析师能在 Shell 环境中直接、高效地完成文本排序工作。日志分析将访问日志按请求耗时排序快速定位最慢的接口。数据清洗对字典文件、用户列表、IP 地址列表进行排序方便后续去重或比较。系统运维将进程列表、磁盘占用信息等按大小排序以便快速定位异常。脚本流程控制在脚本中根据特定规则的排序结果来决定执行的流程或顺序。1.3 为什么说 sort 值得深入学习很多人认为sort太基础不值得花时间。但实际上sort命令的参数非常多功能覆盖了大部分文本处理场景。仅靠一个默认的字典序排序根本无法发挥它的全部价值。比如如何对一列数字按数值大小进行排序而不是按“10 2”这种字典序错误排序如何对 CSV 文件中的某一列进行排序如何实现去重排序如何安全地处理包含特殊字符、空格、Tab 键的文本如何应对大文件的排序而不至于耗尽内存这些问题的答案都在sort命令的各个参数和进阶用法之中。这一篇文章的目的就是帮助你把这些细节一个一个抠明白。2. 环境准备与版本说明2.1 操作系统环境本篇文章的所有命令示例均在主流 Linux 发行版环境下测试通过。理论上只要是标准的 GNU Coreutils 工具集命令行为都是一致的。常见的发行版包括CentOS 7 / CentOS 8 / Rocky LinuxUbuntu 18.04 / Ubuntu 20.04 / Ubuntu 22.04Debian 10 / Debian 11以及各类国产化 Linux 发行版如统信 UOS、银河麒麟 Kylin 等。特别说明国内越来越多的服务器使用银河麒麟等国产操作系统这些系统通常也基于 Linux 内核并自带 GNU Coreutils因此sort命令的用法与标准系统完全一致。在国产化替代的背景下熟练使用这些标准命令反而显得更加重要。2.2 版本查看方式在开始实验之前建议你先查看一下当前系统的sort版本以免不同版本之间存在细微差异。sort --version在常见的 GNU Coreutils 版本中输出类似于sort (GNU coreutils) 8.32 License GPLv3: GNU GPL version 3 or later https://gnu.org/licenses/gpl.html. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.本文所讲的核心功能在 GNU Coreutils 5.x 及以上版本中都已支持因此不必担心版本过旧问题。如果你使用的是 BusyBox 等精简工具箱部分高级参数可能不支持需以对应工具的帮助文档为准。2.3 建议的实验环境为了最大程度地理解本篇文章的示例我建议你准备一台 Linux 虚拟机或者使用云服务器甚至可以在 Windows 上安装 WSLWindows Subsystem for Linux作为实验环境。一个普通的文本编辑器vim、nano 或 VSCode用于创建测试文件。基本的cat、vi、echo命令基础。本文的环境准备并不复杂重点在于后续的命令理解和实战操作。3. 核心语法与基础参数详解sort命令的基本语法格式如下sort [OPTION]... [FILE]...如果不指定 FILE或者 FILE 为-则从标准输入读取数据。多个 FILE 可以同时传入sort会自动将其内容拼接后整体排序。接下来我将按照“由浅入深”的顺序逐一讲解最核心的参数。3.1 字典序排序默认行为默认情况下sort按照字符的字典序按字节值对整行进行排序。对于英文字母就是 a-z 的升序。echo -e orange\napple\nbanana | sort输出apple banana orange这里特别提醒字典序排序比较的是字符编码值因此大写字母在小写字母之前例如Z会排在a前面因为 ASCII 码中大写字母在小写字母前面。这一点在处理包含大小写混合的文本时尤其关键。3.2 忽略大小写排序如果我们希望排序时忽略大小写可以加上-f--ignore-case参数。echo -e Orange\napple\nBanana | sort -f输出apple Banana Orange如果没有加-f实际执行结果是Banana Orange apple因为大写字母的 ASCII 码小于小写字母所以大写开头的单词会排在前面。3.3 数字排序这是初期最容易踩坑的场景。如果文件内容是数字直接使用默认字典序排序会出现这样的问题echo -e 2\n10\n1\n9\n100 | sort输出1 10 100 2 9因为按字典序比较时10的首字符是1100的首字符也是12的首字符是2所以1/10/100会排在2前面9则排在最后。这种结果显然不是我们想要的数字升序结果。解决办法是使用-n--numeric-sort参数echo -e 2\n10\n1\n9\n100 | sort -n输出1 2 9 10 100-n选项会让sort按数值大小来比较而不再按字符编码顺序。3.4 逆序排序-r--reverse参数用于反向排序即从大到小降序排列。echo -e 2\n10\n1\n9\n100 | sort -nr输出100 10 9 2 1在实际运维场景中我们经常需要查看“占用磁盘最大的几个文件”或“耗时最长的几个请求”这时候sort -nr几乎是必用组合。3.5 去重排序-u--unique参数可以在排序的过程中同时去除重复行。它等价于sort后再执行uniq但更高效。echo -e apple\nbanana\napple\ncherry\nbanana | sort -u输出apple banana cherry注意这里说的“重复”是严格按照排序键来判定的。如果使用-k指定了某个字段作为排序键那么去重时只根据该字段是否重复来判断后面会详细说明。3.6 按字段排序这是sort的核心高级功能日常工作中用得非常多。先用一个示例场景来理解。假设有一个成绩单文件scores.txt内容如下Alice:85 Bob:92 Cathy:78 David:88 Eva:95每行由“姓名:分数”组成我们想要按分数从高到低排序该怎么办若直接使用sort -r它是按整行字典序降序排序结果并不是我们要的。正确方法是使用-k参数指定排序字段。-k的基本语法是sort -k 字段起始位置[, 字段结束位置] 文件在这个示例中由于分隔符是冒号我们可以先使用-t指定冒号为字段分隔符再用-k 2指定按第 2 列即分数排序。sort -t : -k 2 -nr scores.txt输出Eva:95 Bob:92 David:88 Alice:85 Cathy:78这里参数的含义是-t :指定字段分隔符为冒号。-k 2指定第 2 字段作为排序键。-n按数值大小比较。-r反向排序。3.7 指定比较的字符范围-k参数不仅是“指定第几列”它还可以精确到字符级别。例如-k 2,2表示仅使用第 2 个字段作为排序键-k 2.3则表示从第 2 个字段的第 3 个字符开始比较-k 2,3表示从第 2 个字段开始到第 3 个字段结束的跨字段内容作为排序键。举一个稍复杂的例子。假设有一个文件mixed.txtapple:30:x apple:5:y apple:100:z banana:20:p我们想先按第 1 个字段排序再按第 2 个字段数值排序。可以这样写sort -t : -k 1,1 -k 2,2n mixed.txt输出apple:5:y apple:30:x apple:100:z banana:20:p这里-k 1,1指定第一个主排序键为第 1 列-k 2,2n指定第二个排序键为第 2 列并进行数值比较。关于-k的详细规则我会在下一个章节中专门展开。3.8 其他常用参数-b--ignore-leading-blanks忽略每行开头的空白字符。默认情况下行首空格可能影响排序结果加上这个参数可有效避免。-M--month-sort按照月份名称缩写JAN、FEB、MAR...排序。-c--check检查文件是否已排序如果已排序则无输出并返回 0否则返回非 0并输出第一条乱序信息。-C--checksilent与-c类似但不输出具体乱序内容。-m--merge合并多个已排序文件不对所有数据重新排序效率更高。-o--output指定输出到文件而不是屏幕。sort -n scores.txt -o sorted_scores.txt命令执行后排序结果写入sorted_scores.txt文件屏幕上不会打印任何内容。这里有一点值得注意-o可以直接指定输入文件作为输出文件比如sort -n data.txt -o data.txt这是安全的原子操作不用担心截断问题。4. 实战演练sort 在数据处理中的完整应用理论知识有时候显得干巴巴只有动手实践才能真正掌握。这一章我用几个贴近日常工作的场景带你把sort命令完整跑一遍。4.1 创建测试数据为了不污染系统目录我们在/tmp下建立一个实验目录。mkdir -p /tmp/sort-demo cd /tmp/sort-demo创建一个访问日志文件access.log模拟服务器的访问记录。格式为IP地址 访问时间 响应码 响应耗时(ms)cat access.log EOF 192.168.1.10 2024-01-01 10:00:01 200 120 10.0.0.5 2024-01-01 10:00:02 404 50 172.16.3.8 2024-01-01 10:00:03 200 89 192.168.1.10 2024-01-01 10:00:04 500 320 10.0.0.5 2024-01-01 10:00:05 200 33 172.16.3.8 2024-01-01 10:00:06 301 10 192.168.1.20 2024-01-01 10:00:07 200 67 10.0.0.8 2024-01-01 10:00:08 404 41 EOF查看文件内容cat access.log4.2 场景一按响应耗时排序定位最慢请求日志中第 5 列是响应耗时单位毫秒。如果我们想快速找出耗时最长的请求sort -k 5 -nr access.log | head -3输出192.168.1.10 2024-01-01 10:00:04 500 320 192.168.1.10 2024-01-01 10:00:01 200 120 172.16.3.8 2024-01-01 10:00:03 200 89由此可见IP 为192.168.1.10的一个请求耗时 320ms是最慢的请求可能需要优先排查。4.3 场景二按 IP 地址排序并统计每个 IP 的请求数量在access.log中第 1 列是 IP 地址。要按 IP 统计请求数常规做法是使用awk配合sort。awk {print $1} access.log | sort | uniq -c | sort -nr这条命令的分解如下awk {print $1}提取每行的第 1 列也就是 IP 地址。sort对 IP 进行排序使得相同 IP 相邻。uniq -c统计每个 IP 出现的次数输出格式为次数 IP。再次sort -nr按次数从大到小排序。输出示例3 192.168.1.10 2 10.0.0.5 2 172.16.3.8 1 10.0.0.8可以看到192.168.1.10请求最多符合前面的耗时排行的判断。4.4 场景三按响应码分类并查看每个响应码的最大耗时如果我们想看每种 HTTP 响应码的最大耗时可以用sort -k 3 -k 4 -nr的方式让第 3 列响应码和第 4 列耗时作为联合排序键。sort -k 3,3 -k 4,4nr access.log输出192.168.1.10 2024-01-01 10:00:04 500 320 192.168.1.10 2024-01-01 10:00:01 200 120 172.16.3.8 2024-01-01 10:00:03 200 89 192.168.1.20 2024-01-01 10:00:07 200 67 10.0.0.5 2024-01-01 10:00:05 200 33 172.16.3.8 2024-01-01 10:00:06 301 10 10.0.0.5 2024-01-01 10:00:02 404 50 10.0.0.8 2024-01-01 10:00:08 404 41注意第 3 列500排在第一位然后从大到小排200但由于相同响应码内部又按耗时降序排列所以200序列从 120ms 开始向下排列这符合我们的预期。4.5 场景四合并多个已排序文件有时候我们会把大日志拆分成多个小文件分别排序最后再合并。这种场景更适合使用sort -m。head -4 access.log part1.log tail -4 access.log part2.log # 先分别对两个文件排序 sort -k 4 -n part1.log -o part1.sorted sort -k 4 -n part2.log -o part2.sorted # 合并假设两个文件都按第4列排好序 sort -m -k 4 -n part1.sorted part2.sorted这里重点说明-m选项只做归并不再进行全量排序因此效率非常高。前提是多个输入文件本身必须已经按相同规则排好序。5. 进阶用法与易错点分析掌握了上面的实战场景之后你已经能解决 90% 的排序需求了。但sort还有很多细节值得深入尤其是那些容易出错、容易让人困惑的地方。下面一一拆解。5.1 关于-k的进一步说明-k选项是sort命令最灵活的组成部分也是出问题最多的地方。它的完整语法可以这样理解-k 起始字段[.起始字符][类型], 结束字段[.结束字符][类型]常用类型标识n按数值排序。r反向排序。f忽略大小写。b忽略该字段开头的空白。u去重。举几个实际例子# 只按第2列排序升序 sort -k 2,2 data.txt # 按第2列的第2个字符开始排序 sort -k 2.2 data.txt # 指定第一个排序键为第1列第二个排序键为第3列数值降序 sort -k 1,1 -k 3,3nr data.txt # 对第2列忽略字母大小写排序 sort -k 2,2f data.txt常见误区很多人以为-k 2就等于“只按第 2 列排序”。实际上-k 2的表示方法是“从第 2 列开始到行尾”不加结束位置时第 2 列之后的全部内容都会参与排序比较。这往往会导致排序结果和预期不一致。所以更严谨的写法是-k 2,2也就是明确指定只使用第 2 列作为排序键。我们用一个简单例子验证cat test.txt EOF b 2 a 10 c 1 a 2 EOF # 使用 -k 1从第1列到行尾 sort -k 1 test.txt输出a 10 a 2 b 2 c 1在这个结果中第 1 列的排序是对的但第 1 列相同的内容中10排在了2前面因为默认是字典序。如果希望第 1 列相同的情况下再按第 2 列数值排序需要这样写sort -k 1,1 -k 2,2n test.txt输出a 2 a 10 b 2 c 1所以认清-k的边界写法是正确使用sort的关键。5.2 关于-t分隔符默认的分隔符是“空白字符”到“非空白字符”的转换处也可以说是每行开头的空格或 Tab 被忽略字段分隔是连续空白。但在实际文件如 CSV、/etc/passwd 文件中分隔符可能是逗号、冒号等。此时就必须使用-t来指定。例如对/etc/passwd文件按用户 ID第 3 列排序sort -t : -k 3,3n /etc/passwd这条命令在运维中非常实用可以快速找出 UID 最小的用户或按序查看用户列表。5.3 实用技巧按人类可读的数字大小排序某些文件里的数字带有单位比如2K、1M、500B。标准sort -n是无法识别K、M、G这样的单位的。GNU sort 提供了-h--human-numeric-sort参数来解决这个问题。echo -e 500M\n2G\n100K\n1T | sort -h输出100K 500M 2G 1T-h在查看磁盘占用大小时特别有用比如du -sh * | sort -h可以非常直观地看到当前目录下哪些文件或文件夹占用的空间最大。5.4 关于排序稳定性默认情况下GNUsort使用的是不稳定排序算法具体与实现有关。不过它提供了-s--stable参数用于保持原始顺序。也就是说如果两个记录排序键相同它们会保持输入文件中的先后顺序。cat record.txt EOF 3 b 1 a 3 a 1 b EOF # 使用稳定排序 sort -s -k 1,1 record.txt输出1 a 1 b 3 b 3 a注意3 b仍然在3 a前面因为它们排序键同为3在输入中3 b先出现所以稳定排序保持了该顺序。不稳定的排序则可能让它们互换位置。在数据处理中如果后续步骤依赖稳定的排序结果务必加上-s。5.5 随机排序与乱序sort命令还可以实现随机排序主要用于抽样、洗牌等需求。sort -R data.txt-R--random-sort会基于随机哈希函数对行进行混排每次执行结果可能不同。如果想固定随机种子可用--random-source指定随机源。不过如果你只是想将一个大文件随机打乱更高效的方式是用shuf命令它是 GNU Coreutils 中的专用工具。但了解sort -R也算多一种备选方案。6. 常见问题与排查思路下表总结了一些关于sort命令的高频问题、原因分析及解决思路。问题现象常见原因解决思路数字排序结果不对比如 10 排在 2 前面未使用数值排序参数加上-n参数想按某一列排序但结果却跟整行有关-k未指定结束位置导致从起始列到行尾都参与排序明确写成-k 列,列排序结果中大小写顺序不符合预期默认按 ASCII 码比较大写字母在小写字母前加上-f忽略大小写CSV 文件按某一列排序失败默认分隔符不是逗号使用-t ,指定分隔符按数字带单位K、M、G排序错误-n不能识别容量单位改用-h检查文件是否已排序不想输出全部内容不了解检查参数使用-c或-C合并多个已排序文件速度很慢没有使用归并模式而是重新全量排序使用-m参数行首空格导致排序结果异常空白被当成字段的一部分使用-b忽略前导空白7. 最佳实践与工程建议实践出真知但合理的经验能让我们少踩很多坑。这里总结我在项目中使用sort命令的几点建议。7.1 优先明确排序键的范围在编写任何sort命令之前先想清楚“我要按第几列排序这个排序键是否一直延续到行尾”如果答案是只想按某一列就写成-k n,n。不要偷懒写成-k n偷懒的代价是结果可能悄悄地错。7.2 结合-o安全输出很多初学者习惯用重定向sort data.txt data.txt这种做法相当危险因为 Shell 会先打开输出文件导致输入文件被截断为空文件数据丢失。正确做法是sort data.txt -o data.txtsort会先将结果写入临时文件再安全替换原文件避免数据损失。7.3 和uniq搭配时注意顺序uniq只能去除“连续重复”的行所以在使用uniq前必须确保内容已经排序。常见的流水线是sort data.txt | uniq -c如果直接对未排序的文件执行uniq -c统计结果会不准确因为相同的行如果没连在一起会被当作不同的行处理。另外sort -u可以替代sort | uniq组合性能更高且能指定排序键去重适合更复杂的场景。7.4 注意 locale 环境的影响sort默认排序顺序会受到LC_ALL、LANG等环境变量的影响。例如在中文 locale 环境下汉字的排序可能不会按照拼音或 Unicode 编码顺序而在某些 locale 下英文字母大小写比较规则也不同。如果需要程序化的确定性的排序可以在命令前指定环境变量LC_ALLC sort data.txtLC_ALLC表示使用 C 语言环境按字节值直接比较结果最稳定在脚本中特别好用。7.5 大文件的处理思路如果文件特别大比如几个 GB 的日志sort可能会消耗较多内存和临时磁盘空间。此时建议结合-m归并模式将问题分解将大文件按某种规则拆分成多个小文件。分别对小文件排序。使用sort -m合并各个已排序文件。另外可以通过-T参数指定临时目录避免默认临时目录空间不足sort -T /data/tmp -n bigfile.txt7.6 安全与权限意识在生产环境处理日志或系统配置时永远要先确认当前用户具备相应文件的操作权限涉及覆盖写入的场景先备份原文件。尤其当在脚本中使用sort -o覆盖关键配置文件时建议先使用-c检查原始文件的排序状态或先复制一份备份。8. 总结与下一步学习方向这篇文章从sort命令的背景与基础概念讲起详细拆解了排序的核心参数与用法包括字典序排序、数字排序、逆序排序、去重排序、字段排序、归并排序、随机排序以及围绕这些用法展开的多个实战案例。另外我们还总结了常见的踩坑点比如-k的边界问题、-t分隔符、-h对容量的支持、稳定性控制、环境变量对排序结果的影响以及安全使用-o的建议。到这里你已经可以非常灵活地在 Shell 中处理绝大多数的排序需求。下一步你可以继续延伸学习uniq命令与sort强绑定的去重统计工具。awk命令更强大的文本处理字段提取工具。cut命令快速截取文本字段。grep与sort的组合过滤加排序是日志分析的黄金搭档。shuf命令随机打乱文本行常用于样本抽取。把这些命令串联起来你就拥有了一个非常高效的 Shell 文本处理工具箱。如果本文对你有帮助可以收藏备用后续使用sort时随手查阅会非常方便。动手实践才是最好的学习途径快打开终端拿几个真实的日志或数据文件试一试吧。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门