sort命令
sort是排序工具,它完美贯彻了Unix哲学:"只做一件事,并做到完美"。它的排序功能极强、极完整,只要文件中的数据足够规则,它几乎可以排出所有想要的排序结果,是一个非常优质的工具。
虽然sort很强大,但它的选项很少,使用方法也很简单。更让人觉得它成功的地方在于:即使想要实现复杂、完整的sort功能,所使用的选项和一般使用时的选项没什么不同。只不过要实现复杂功能时,必须得理解sort是如何工作的。
也就是说,没搞懂sort工作机制时,它也能完成任务,指哪就能打哪,但没被指到的地方难免会有所偏差和疑惑。只有搞懂了sort机制,才能真正的指哪打哪,结果中一丝偏差也没有,即使出现了偏差也知道是为什么。
本文先解释sort命令的常用选项,再给出sort的简单使用示例,用于初步解释sort各选项,最后对sort深入说明。更完整的选项说明可参考info sort的译文:sort命令中文手册(info sort翻译)。
选项说明
sort读取每一行输入,并按照指定的分隔符将每一行划分成多个字段,这些字段就是sort排序的对象。同时,sort可以指定按照何种排序规则进行排序,如按照当前字符集排序规则(这是默认排序规则)、按照字典排序规则、按照数值排序规则、按照月份排序规则、按照文件大小格式(k<M<G)。还可以去除重复行,指定降序或升序(默认)的排序方式。
默认的排序规则为字符集排序规则,通常几种常见字符的顺序为:"空字符串<空白字符<数值<a<A<b<B<...<z<Z",这也是字典排序的规则。
语法格式:
sort [OPTION]... [FILE]... 选项说明: -c:检测给定的文件是否已经排序。如未排序,则会输出诊断信息,提示从哪一行开始乱序。 -C:类似于"-c",只不过不输出任何诊断信息。可以通过退出状态码1判断出文件未排序。 -m:对给定的多个已排序文件进行合并。在合并过程中不做任何排序动作。 -b:忽略字段的前导空白字符。空格数量不固定时,该选项几乎是必须要使用的。"-n"选项隐含该选项。 -d:按照字典顺序排序,只支持字母、数值、空白。除了特殊字符,一般情况下基本等同于默认排序规则。 --debug:将显示排序的过程以及每次排序所使用的字段、字符。同时还会在最前几行显示额外的信息。 -f:将所有小写字母当成大写字母。例如,"b"和"B"是相同的。 :在和"-u"选项一起使用时,如果排序字段的比较结果相等,则丢弃小写字母行。 -k:指定要排序的key,key由字段组成。key格式为"POS1[,POS2]",POS1为key起始位置,POS2为key结束位置。 -n:按数值排序。空字符串""或"\0"被当作空。该选项除了能识别负号"-",其他所有非数字字符都不识别。 :当按数值排序时,遇到不识别的字符时将立即结束该key的排序。 -M:按字符串格式的月份排序。会自动转换成大写,并取缩写值。规则:unknown<JAN<FEB<...<NOV<DEC。 -o:将结果输出到指定文件中。 -r:默认是升序排序,使用该选项将得到降序排序的结果。 :注意:"-r"不参与排序动作,只是操作排序完成后的结果。 -s:禁止sort做"最后的排序"。 -t:指定字段分隔符。 :对于特殊符号(如制表符),可使用类似于-t$'\t'或-t'ctrl+v,tab'(先按ctrl+v,然后按tab键)的方法实现。 -u:只输出重复行的第一行。结合"-f"使用时,重复的小写行被丢弃。
sort示例
此小节为sort的简单用法示例,也是平时最可能用上的示例。如果只是为了使用sort,而不是为了刨根问题,本小节已经足够。
假设当前已有文件system.txt,内容如下:其中空白部分为单个制表符。
[root@localhost ~]# vi system.txt 1 mac 2000 500 2 winxp 4000 300 3 bsd 1000 600 4 linux 1000 200 5 SUSE 4000 300 6 Debian 600 200
(1).不加任何选项时,将对整行从第一个字符开始依次向后直到行尾按照默认的字符集排序规则做升序排序。
[root@localhost ~]# sort system.txt 1 mac 2000 500 2 winxp 4000 300 3 bsd 1000 600 4 linux 1000 200 5 SUSE 4000 300 6 Debian 600 200
由于每行的第一个字符1<2<3<4<5<6,所以结果如上。
(2).以第三列为排序列进行排序。由于要划分字段,所以指定字段分隔符。指定制表符这种无法直接输入的特殊字符的方式是$'\t'。
[root@localhost ~]# sort -t $'\t' -k3 system.txt 1 mac 2000 500 2 winxp 4000 300 3 bsd 1000 600 4 linux 1000 200 5 SUSE 4000 300 6 Debian 600 200
结果中虽然1000<2000<4000的顺序是对了,但600却排在最后面,因为这是按照默认字符集排序规则进行排序的,字符6大于4,所以排最后一行。
[root@localhost ~]# last|grep '192'|awk '{S[$3]++} END{for(a in S) {print a,S[a]}}'|sort -rn 192.168.1.5 6 192.168.1.12 1
[root@localhost files]# vi testsort.txt google 110 5000 baidu 100 5000 guge 50 3000 sohu 100 4500 ~
让这个文件按公司的字母顺序排序,也就是按第一个域进行排序:
[root@localhost files]# sort -t ' ' -k 1 testsort.txt baidu 100 5000 google 110 5000 guge 50 3000 sohu 100 4500
[root@master ~]# cat seq.txt
banana
apple
pear
orange
[root@master ~]# sort seq.txt
apple
banana
orange
pear
[root@master ~]# sort -r number.txt #降序排序
9
8
7
6
5
4
3
2
1
[root@master ~]# cat number.txt
9
8
7
6
5
4
3
2
1
[root@master ~]# sort number.txt 升序排序。
1
2
3
4
5
6
7
8
9
[root@master ~]# sort -u -n number.txt 去除重复的数值
1
2
3
4
5
6
7
8
9
[root@master ~]# sort -r number.txt -o number1.txt
[root@master ~]# cat number1.txt
9
8
7
6
5
4
3
2
1
[root@master ~]# sort number.txt
1 12 2 23 3 4 45 5 6 65 7 76 8 89 9
[root@master ~]# sort -n number.txt 加上-n以数值排序
1 2 3 4 5 6 7 8 9 12 23 45 65 76 89
[root@master ~]# vi facebook.txt
banana:30:5.5
apple:10:2.5
pear:90:2.3
orange:20:3.4
~
[root@master ~]# sort -n -k 2 -t : facebook.txt 以冒号为分隔符,第二列数值以升序排序。
apple:10:2.5
orange:20:3.4
banana:30:5.5
pear:90:2.3
[root@master ~]# sort -n -r -k 2 -t : facebook.txt 第二列降序排序。
pear:90:2.3
banana:30:5.5
orange:20:3.4
apple:10:2.5
其他的sort常用选项
[root@master ~]# vi facebook1.txt
baidu 100 5000
google 110 5000
guge 50 3000
sohu 100 4500
看到了吧,就直接用-k 1设定就可以了。(其实此处并不严格,稍后你就会知道)
[root@master ~]# sort -n -t ' ' -k 2 facebook1.txt
guge 50 3000
baidu 100 5000
sohu 100 4500
google 110 5000
[root@master ~]# sort -n -t ' ' -k 2 -k 3 facebook1.txt
guge 50 3000
sohu 100 4500
baidu 100 5000
google 110 5000
[root@master ~]# sort -n -t ' ' -k 3r -k 2 facebook1.txt
baidu 100 5000
google 110 5000
sohu 100 4500
guge 50 3000
此处有使用了一些小技巧,你仔细看看,在-k 3后面偷偷加上了一个小写字母r。你想想,再结合我们上一篇文章,能得到答案么?揭晓:r和-r选项的作用是一样的,就是表示逆序。因为sort默认是按照升序排序的,所以此处需要加上r表示第三个域(员工平均工资)是按照降序排序。此处你还可以加上n,就表示对这个域进行排序时,要按照数值大小进行排序,举个例子吧
[root@master ~]# sort -t ' ' -k 3nr -k 2n facebook1.txt
baidu 100 5000
google 110 5000
sohu 100 4500
guge 50 3000
突发奇想,从公司英文名称的第二个字母开始进行排序:
[root@master ~]# sort -t ' ' -k 1.2 facebook1.txt
baidu 100 5000
sohu 100 4500
google 110 5000
guge 50 3000
[root@master ~]# sort -t ' ' -k 1.2,1.2 -k 3,3nr facebook1.txt
baidu 100 5000
google 110 5000
sohu 100 4500
guge 50 3000
由于只对第二个字母进行排序,所以我们使用了-k 1.2,1.2的表示方式,表示我们“只”对第二个字母进行排序。(如果你问“我使用-k 1.2怎么不行?”,当然不行,因为你省略了End部分,这就意味着你将对从第二个字母起到本域最后一个字符为止的字符串进行排序)。对于员工工资进行排 序,我们也使用了-k 3,3,这是最准确的表述,表示我们“只”对本域进行排序,因为如果你省略了后面的3,就变成了我们“对第3个域开始到最后一个域位置的内容进行排序” 了。
在modifier部分还可以用到哪些选项?
[root@master ~]# sort -n -k 2 -u facebook1.txt
guge 50 3000
baidu 100 5000
google 110 5000
当设定以公司员工域进行数值排序,然后加-u后,sohu一行就被删除了!原来-u只识别用-k设定的域,发现相同,就将后续相同的行都删除。
[root@master ~]# sort -k 1 -u facebook1.txt
baidu 100 5000
google 110 5000
guge 50 3000
sohu 100 4500
[root@master ~]# sort -k 1.1,1.1 -u facebook1.txt
baidu 100 5000
google 110 5000
sohu 100 4500
这个例子也同理,开头字符是g的guge就没有幸免于难。
[root@master ~]# sort -k 2 -k 3 -u facebook1.txt
sohu 100 4500
baidu 100 5000
google 110 5000
guge 50 3000
咦!这里设置了两层排序优先级的情况下,使用-u就没有删除任何行。原来-u是会权衡所有-k选项,将都相同的才会删除,只要其中有一级不同都不会轻易删除的:)(不信,你可以自己加一行sina 100 4500试试看)
[root@master ~]# vi facebook1.txt
baidu 100 5000
google 110 5000
guge 50 3000
sohu 100 4500
sina 100 4500
[root@master ~]# sort -n -k 2 -k 3 -u facebook1.txt
guge 50 3000
sohu 100 4500
baidu 100 5000
google 110 5000
最诡异的排序:
[root@master ~]# sort -n -k 2.2 -k 3.1 facebook1.txt 升序
guge 50 3000
sina 100 4500
sohu 100 4500
baidu 100 5000
google 110 5000
[root@master ~]# sort -n -k 2.2 -k 3.1 -r facebook1.txt 降序。
google 110 5000
baidu 100 5000
sohu 100 4500
sina 100 4500
guge 50 3000
[root@master ~]# sort -n -k 2.2 -k 3.1 -k 1r facebook1.txt
guge 50 3000
sohu 100 4500
sina 100 4500
baidu 100 5000
google 110 5000
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?