sort命令使用说明

1、命令概述

sort命令是在Linux里非常有用,它将文件进行排序,并将排序结果标准输出。sort命令既可以从特定的文件,也可以从stdin中获取输入。

2、命令语法

sort 【选项】 【文件】

3、命令选项

-b:忽略每行前面开始出的空格字符
-c:检查文件是否已经按照顺序排序
-d:排序时,处理英文字母、数字及空格字符外,忽略其他的字符
-f:排序时,将小写字母视为大写字母(忽略大小写)
-g:按通用数值排序,支持科学计数法
-i:排序时,除了040至176之间的ASCII字符外,忽略其他的字符
-m:将几个排序号的文件进行合并
-M:将前面3个字母依照月份的缩写进行排序
-n:依照数值的大小排序
-o <输出文件>:将排序后的结果存入原文件
-r:以相反的顺序来排序,
-k:指定需要排序的栏位
-t <分隔字符>:指定排序时所用的栏位分隔字符
-u:去除重复的行

4、命令示例

4.1 sort将文件/文本的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出:

 1 [root@lzg ~]# cat a.txt 
 2 5
 3 11
 4 1
 5 156
 6 11
 7 23
 8 156
 9 256
10 [root@lzg ~]# sort a.txt 
11 1
12 11
13 11
14 156
15 156
16 23
17 256
18 5
19 [root@lzg ~]# cat b.txt 
20 aaa:30:1.6
21 bbb:10:2.5
22 ccc:50:3.3
23 ddd:20:4.2
24 bbb:10:2.5
25 eee:80:5.4
26 eee:60:5.1
27 [root@lzg ~]# sort b.txt 
28 aaa:30:1.6
29 bbb:10:2.5
30 bbb:10:2.5
31 ccc:50:3.3
32 ddd:20:4.2
33 eee:60:5.1
34 eee:80:5.4
35 [root@lzg ~]# 

4.2 忽略相同行使用-u选项或者uniq:

 1 [root@lzg ~]# sort a.txt 
 2 1
 3 11
 4 11
 5 156
 6 156
 7 23
 8 256
 9 5
10 [root@lzg ~]# sort -u a.txt 
11 1
12 11
13 156
14 23
15 256
16 5
17 [root@lzg ~]# sort b.txt 
18 aaa:30:1.6
19 bbb:10:2.5
20 bbb:10:2.5
21 ccc:50:3.3
22 ddd:20:4.2
23 eee:60:5.1
24 eee:80:5.4
25 [root@lzg ~]# sort -u b.txt 
26 aaa:30:1.6
27 bbb:10:2.5
28 ccc:50:3.3
29 ddd:20:4.2
30 eee:60:5.1
31 eee:80:5.4
32 [root@lzg ~]# 

或者使用uniq:

 1 [root@lzg ~]# sort a.txt 
 2 1
 3 11
 4 11
 5 156
 6 156
 7 23
 8 256
 9 5
10 [root@lzg ~]# sort a.txt | uniq
11 1
12 11
13 156
14 23
15 256
16 5
17 [root@lzg ~]# sort b.txt 
18 aaa:30:1.6
19 bbb:10:2.5
20 bbb:10:2.5
21 ccc:50:3.3
22 ddd:20:4.2
23 eee:60:5.1
24 eee:80:5.4
25 [root@lzg ~]# sort b.txt | uniq
26 aaa:30:1.6
27 bbb:10:2.5
28 ccc:50:3.3
29 ddd:20:4.2
30 eee:60:5.1
31 eee:80:5.4
32 [root@lzg ~]# 

4.3 -n 依照数值的大小顺序排列:

 1 [root@lzg ~]# cat a.txt 
 2 5
 3 11
 4 1
 5 156
 6 11
 7 23
 8 156
 9 256
10 [root@lzg ~]# sort -n a.txt 
11 1
12 5
13 11
14 11
15 23
16 156
17 156
18 256
19 [root@lzg ~]# cat b.txt 
20 aaa:30:1.6
21 bbb:10:2.5
22 ccc:50:3.3
23 ddd:20:4.2
24 bbb:10:2.5
25 eee:80:5.4
26 eee:60:5.1
27 [root@lzg ~]# sort -n b.txt 
28 aaa:30:1.6
29 bbb:10:2.5
30 bbb:10:2.5
31 ccc:50:3.3
32 ddd:20:4.2
33 eee:60:5.1
34 eee:80:5.4
35 [root@lzg ~]# 

4.4 -o <输出文件>:将排序后的结果存入原文件。

由于sort默认是把结果输出到标准输出,所以需要用重定向才能将结果写入文件,形如sort filename > newfile。但是,如果你想把排序结果输出到原文件中,用重定向可就不行了。

 1 [root@lzg ~]# ls
 2 a.txt  b.txt  c.txt
 3 [root@lzg ~]# cat c.txt 
 4 8
 5 1
 6 3
 7 2
 8 [root@lzg ~]# sort c.txt 
 9 1
10 2
11 3
12 8
13 [root@lzg ~]# sort c.txt > d.txt            #输出结果重定向到d.txt
14 [root@lzg ~]# ls
15 a.txt  b.txt  c.txt  d.txt
16 [root@lzg ~]# cat d.txt                     #查看内容,排序后的
17 1
18 2
19 3
20 8
21 [root@lzg ~]# sort c.txt > c.txt            #类似方法重定向到原文件 c.txt
22 [root@lzg ~]# ls
23 a.txt  b.txt  c.txt  d.txt
24 [root@lzg ~]# cat c.txt                     #查看内容,将原文件清空了
25 [root@lzg ~]# 

这个时候可以使用 -o 选项,将结果写入原文件。

 1 [root@lzg ~]# cat c.txt 
 2 8
 3 1
 4 3
 5 2
 6 [root@lzg ~]# sort c.txt -o c.txt 
 7 [root@lzg ~]# cat c.txt 
 8 1
 9 2
10 3
11 8
12 [root@lzg ~]# 

4.5 -c:检查文件是否已经按照顺序排序

 1 [root@lzg ~]# cat a.txt 
 2 5  dsfsd  5000  300
 3 1  hyj  1000  600
 4 156  efcv  4000  700
 5 11  ghjty  600  566
 6 23  rfdfg  7569  500
 7 256 hjtf  6000  230
 8 [root@lzg ~]# sort -c a.txt 
 9 sort: a.txt:2: disorder: 1  hyj  1000  600     #提示无序
10 [root@lzg ~]# cat c.txt 
11 1
12 2
13 3
14 8
15 [root@lzg ~]# sort -c c.txt      #已排序的,没有提示
16 [root@lzg ~]# 

4.6 sort的-n、-r、-k、-t选项的使用:

 1 [root@lzg ~]# cat b.txt 
 2 aaa:30:1.6
 3 bbb:10:2.5
 4 ccc:50:3.3
 5 ddd:20:4.2
 6 bbb:10:2.5
 7 eee:80:5.4
 8 eee:60:5.1
 9 [root@lzg ~]# sort -n -k2 -t: b.txt 
10 bbb:10:2.5
11 bbb:10:2.5
12 ddd:20:4.2
13 aaa:30:1.6
14 ccc:50:3.3
15 eee:60:5.1
16 eee:80:5.4
17 [root@lzg ~]# sort -nr -k3 -t: b.txt 
18 eee:80:5.4
19 eee:60:5.1
20 ddd:20:4.2
21 ccc:50:3.3
22 bbb:10:2.5
23 bbb:10:2.5
24 aaa:30:1.6
25 [root@lzg ~]# 
#-n是按照数字大小排序,-r是以相反顺序,-k是指定需要排序的栏位、2是代表第二栏的,-t指定栏位分隔符为冒号

有时候学习脚本,你会发现sort命令后面跟了一堆类似-k1,2,或者-k1.2 -k3.4的东东,有些匪夷所思。今天,我们就来搞定它—-k选项!

1、准备以下素材,test.txt 第一个域是公司名称,第二个域是公司人数,第三个域是员工平均工资,a.txt 和 b.txt :

 1 [root@lzg ~]# cat test.txt 
 2 zaidu 200 5000
 3 guge 50 3000
 4 sohu 80 4500
 5 google 210 5000
 6 zdfg 150 900
 7 hyke 80 800
 8 [root@lzg ~]# cat a.txt 
 9 5  dsfsd  5000  300
10 1  hyj  1000  600
11 156  efcv  4000  700
12 11  ghjty  800  500
13 23  rfdfg  600  500
14 256 hjtf  4000  230
15 [root@lzg ~]# cat b.txt 
16 dc:30:1.6:df
17 ab:10:2.5:1c
18 4f:50:3.3:d6
19 dd:20:4.2:8a
20 bb:10:2.5:f1
21 5e:80:5.4:e3
22 6e:60:5.1:ad
23 [root@lzg ~]# 

2、让 test.txt 按公司的字母顺序排序,也就是按第一个域进行排序:(这个test.txt文件有三个域) 

 

 1 [root@lzg ~]# sort test.txt            #默认按照升序自动排序
 2 google 210 5000
 3 guge 50 3000
 4 hyke 80 800
 5 sohu 80 4500
 6 zaidu 200 5000
 7 zdfg 150 900
 8 或者
 9 [root@lzg ~]# sort -t' ' -k1 test.txt     #-t' '指定栏位分隔符为空格,-k1指定需要排序的栏位是1栏位
10 google 210 5000
11 guge 50 3000
12 hyke 80 800
13 sohu 80 4500
14 zaidu 200 5000
15 zdfg 150 900
16 或者
17 [root@lzg ~]# sort -t ' ' -k 1 test.txt    #-t和-k的可以用空格分开
18 google 210 5000
19 guge 50 3000
20 hyke 80 800
21 sohu 80 4500
22 zaidu 200 5000
23 zdfg 150 900
24 [root@lzg ~]# 

以上开头是以字母开始的,如果是数字呢?

 1 [root@lzg ~]# sort a.txt 
 2 11  ghjty  800  500
 3 156  efcv  4000  700
 4 1  hyj  1000  600
 5 23  rfdfg  600  500
 6 256 hjtf  4000  230
 7 5  dsfsd  5000  300
 8 [root@lzg ~]# sort -t' ' -k1 a.txt    #此处不加-t' '也可以,因为排序的是第一个域,如果是后面的,需要加
 9 11  ghjty  800  500
10 156  efcv  4000  700
11 1  hyj  1000  600
12 23  rfdfg  600  500
13 256 hjtf  4000  230
14 5  dsfsd  5000  300
15 [root@lzg ~]# 
以上可以看到数字排序不是按照正常数值大小的方式排序的,而是按照首字符的大小排序,那这种情况怎么办呢?请看下面的方式
 1 [root@lzg ~]# sort -n a.txt 
 2 1  hyj  1000  600
 3 5  dsfsd  5000  300
 4 11  ghjty  800  500
 5 23  rfdfg  600  500
 6 156  efcv  4000  700
 7 256 hjtf  4000  230
 8 [root@lzg ~]# sort -k1n a.txt        #标准写法
 9 1  hyj  1000  600
10 5  dsfsd  5000  300
11 11  ghjty  800  500
12 23  rfdfg  600  500
13 156  efcv  4000  700
14 256 hjtf  4000  230
15 [root@lzg ~]# 
 1 [root@lzg ~]# sort -k3n a.txt        
 2 23  rfdfg  600  500
 3 11  ghjty  800  500
 4 1  hyj  1000  600
 5 156  efcv  4000  700
 6 256 hjtf  4000  230
 7 5  dsfsd  5000  300
 8 [root@lzg ~]# sort -t' ' -k3n a.txt 
 9 11  ghjty  800  500
10 156  efcv  4000  700
11 1  hyj  1000  600
12 23  rfdfg  600  500
13 5  dsfsd  5000  300
14 256 hjtf  4000  230
15 [root@lzg ~]# 
以上可以看到用空格隔开的不加 -t' ' 也可以。注意:空格的需要加单引号 '' ,其他类型的可不加,但最好是加单引号,看下面的例子:
 1 [root@lzg ~]# sort -t: -k2n b.txt 
 2 ab:10:2.5:1c
 3 bb:10:2.5:f1
 4 dd:20:4.2:8a
 5 dc:30:1.6:df
 6 4f:50:3.3:d6
 7 6e:60:5.1:ad
 8 5e:80:5.4:e3
 9 [root@lzg ~]# sort -t':' -k2n b.txt 
10 ab:10:2.5:1c
11 bb:10:2.5:f1
12 dd:20:4.2:8a
13 dc:30:1.6:df
14 4f:50:3.3:d6
15 6e:60:5.1:ad
16 5e:80:5.4:e3
17 [root@lzg ~]# 

3、我想让 test.txt 按照公司人数排序:

1 [root@lzg ~]# sort -t' ' -k2n test.txt 
2 guge 50 3000
3 hyke 80 800
4 sohu 80 4500
5 zdfg 150 900
6 zaidu 200 5000
7 google 210 5000
8 [root@lzg ~]# 

此处出现一个问题,那就是hyke和sohu的公司人数相同,这个时候怎么办呢?按照默认规矩,是从第一个域开始进行升序排序,因此hyke排在了sohu前面。

4、我想让 test.txt 按照公司人数排序 ,人数相同的按照员工平均工资升序排序:

1 [root@lzg ~]# sort -t' ' -k2n -k3n test.txt 
2 guge 50 3000
3 hyke 80 800
4 sohu 80 4500
5 zdfg 150 900
6 zaidu 200 5000
7 google 210 5000
8 [root@lzg ~]# 
加了一个-k2 -k3就解决了问题。sort支持这种设定,就是说设定域排序的优先级,先以第2个域进行排序,如果相同,再以第3个域进行排序。(如果你愿意,可以一直这么写下去,设定很多个排序优先级)

5、我想让 test.txt 按照员工工资降序排序,如果员工工资相同的,则按照公司人数升序排序:

 1 [root@lzg ~]# sort -t' ' -k3nr -k2n test.txt    #n必须要跟在-k的后面
 2 zaidu 200 5000
 3 google 210 5000
 4 sohu 80 4500
 5 guge 50 3000
 6 zdfg 150 900
 7 hyke 80 800
 8 [root@lzg ~]# 

6、-k选项的具体语法格式:

-k选项的语法格式如下:
[ FStart [ .CStart ] ] [ Modifier ] [ , [ FEnd [ .CEnd ] ][ Modifier ] ]
这个语法格式可以被其中的逗号(“,”)分为两大部分,Start部分和End部分。
先给你灌输一个思想,那就是“如果不设定End部分,那么就认为End被设定为行尾”。这个概念很重要的,但往往你不会重视它。
Start部分也由三部分组成,其中的Modifier部分就是我们之前说过的类似n和r的选项部分。我们重点说说Start部分的FStart和C.Start。
C.Start也是可以省略的,省略的话就表示从本域的开头部分开始。之前例子中的-k 2和-k 3就是省略了C.Start的例子喽。
FStart.CStart,其中FStart就是表示使用的域,而CStart则表示在FStart域中从第几个字符开始算“排序首字符”。
同理,在End部分中,你可以设定FEnd.CEnd,如果你省略.CEnd,则表示结尾到“域尾”,即本域的最后一个字符。或者,如果你将CEnd设定为0(零),也是表示结尾到“域尾”。

7、test.txt 从公司英文名称的第二个字母开始进行排序:

1 [root@lzg ~]# sort -t' ' -k1.2 test.txt 
2 zaidu 200 5000
3 zdfg 150 900
4 sohu 80 4500
5 google 210 5000
6 guge 50 3000
7 hyke 80 800
8 [root@lzg ~]# 

使用 -k 1.2,这就表示第一个域的第二个字符开始到本域的最后一个字符为止的字符串进行排序。你会发现zaid因为第二个字母是a而名列榜首。sohu和 google第二个字符都是o,但sohu的h在google的o前面,所以sohu排在googl的前面。

8、只针对公司英文名称的第二个字母进行排序,如果相同的按照员工工资进行降序排序:

1 [root@lzg ~]# sort -t' ' -k1.2,1.2 -k3,3nr test.txt 
2 zaidu 200 5000
3 zdfg 150 900
4 google 210 5000
5 sohu 80 4500
6 guge 50 3000
7 hyke 80 800
8 [root@lzg ~]# 
由于只对第二个字母进行排序,所以我们使用了-k 1.2,1.2的表示方式,表示我们“只”对第二个字母进行排序。(如果你问“我使用-k 1.2怎么不行?”,当然不行,因为你省略了End部分,这就意味着你将对从第二个字母起到本域最后一个字符为止的字符串进行排序)。对于员工工资进行排序,我们也使用了-k 3,3,这是最准确的表述,表示我们“只”对本域进行排序,因为如果你省略了后面的3,就变成了我们“对第3个域开始到最后一个域位置的内容进行排序” 了。

9、在modifier部分还可以用到哪些选项?
可以用到b、d、f、i、n 或 r。
其中n和r你肯定已经很熟悉了。
b表示忽略本域的签到空白符号。
d表示对本域按照字典顺序排序(即,只考虑空白和字母)。
f表示对本域忽略大小写进行排序。

10、关于-k和-u联合使用的例子:

 1 [root@lzg ~]# cat face.txt 
 2 google 110 5000
 3 baidu 100 5000
 4 guge 50 3000
 5 sohu 100 4500
 6 [root@lzg ~]# sort -t' ' -k2n face.txt 
 7 guge 50 3000
 8 baidu 100 5000
 9 sohu 100 4500
10 google 110 5000
11 [root@lzg ~]# sort -t' ' -k2n -u face.txt 
12 guge 50 3000
13 baidu 100 5000
14 google 110 5000
15 [root@lzg ~]# 
当设定以公司员工域进行数值排序,然后加-u后,sohu一行就被删除了!原来-u只识别用-k设定的域,发现相同,就将后续相同的行都删除。
1 [root@lzg ~]# sort -k1.1,1.1 -u face.txt 
2 baidu 100 5000
3 google 110 5000
4 sohu 100 4500
5 [root@lzg ~]# 
这个例子也同理,开头字符是g的guge就没有幸免于难。
1 [root@lzg ~]# sort -n -k2 -k3 -u face.txt 
2 guge 50 3000
3 sohu 100 4500
4 baidu 100 5000
5 google 110 5000
6 [root@lzg ~]# 
这里设置了两层排序优先级的情况下,使用-u就没有删除任何行。原来-u是会权衡所有-k选项,将都相同的才会删除,只要其中有一级不同都不会轻易删除的

11、另类排序:

1 [root@lzg ~]# sort -n -k2.2,3.1 face.txt 
2 guge 50 3000
3 baidu 100 5000
4 sohu 100 4500
5 google 110 5000
6 [root@lzg ~]# 

以第二个域的第二个字符开始到第三个域的第一个字符结束的部分进行排序。
第一行,会提取0 3,第二行提取00 5,第三行提取00 4,第四行提取10 5。
又因为sort认为0小于00小于000小于0000….
因此0 3肯定是在第一个。10 5肯定是在最后一个。但为什么00 5却在00 4前面呢?
原来“跨域的设定是个假象”,sort只会比较第二个域的第二个字符到第二个域的最后一个字符的部分,而不会把第三个域的开头字符纳入比较范围。当发现00和00相同时,sort就会自动比较第一个域去了。当然baidu在sohu前面了,用一个例子即可证明,如下:

1 [root@lzg ~]# sort -n -k2.2,3.1 -k1.1r face.txt 
2 guge 50 3000
3 sohu 100 4500
4 baidu 100 5000
5 google 110 5000
6 [root@lzg ~]# 

其实上面的例子类似下面的例子:

 1 [root@lzg ~]# sort -n -k2.2,3.1 face.txt 
 2 guge 50 3000
 3 baidu 100 5000
 4 sohu 100 4500
 5 google 110 5000
 6 [root@lzg ~]# sort -n -k2.2 face.txt 
 7 guge 50 3000
 8 baidu 100 5000
 9 sohu 100 4500
10 google 110 5000
11 [root@lzg ~]# 

12、有时候在sort命令后会看到+1 -2这些符号,这是什么意思?
关于这种语法,最新的sort是这么进行解释的:
On older systems, `sort’ supports an obsolete origin-zero syntax `+POS1 [-POS2]‘ for specifying sort keys. POSIX 1003.1-2001 (*note Standards conformance::) does not allow this; use `-k’ instead.
原来,这种古老的表示方式已经被淘汰了,以后可以理直气壮的鄙视使用这种表示方法的脚本喽!
(为了防止古老脚本的存在,在这再说一下这种表示方法,加号表示Start部分,减号表示End部分。最最重要的一点是,这种方式方法是从0开始计数的,以前所说的第一个域,在此被表示为第0个域。以前的第2个字符,在此表示为第1个字符。)

 

posted @ 2019-10-22 17:37  网络小白-lzg  阅读(1048)  评论(0编辑  收藏  举报