0%

sort命令

一、常用用法

1
sort [-d | -g | -M | -h | -n] [-r] [-f] [-t CHAR] [-k KEYDEF [-k KEYDEF ... -k KEYDEF]] FILE

二、含义与选项

2.1、含义

对文件中的记录进行排序。

2.2、选项表示的意思

“-d”:按照字典序排序,默认就是按照字典序排序的。
“-g”:按照数字大小排序,支持科学计数表示法。
“-M”:按照月份大小排序,比如JAN<DEC
“-h”:支持识别人类可读形式单位然后进行排序,比如2K<1G
“-n”:按照数字大小排序,不支持科学计数表示法。
“-r”:表示反方向排序。
“-f”:排序比较时,忽略大小写。
“-t CHAR”:以“CHAR”字符作为字段间分隔符,默认是以“空格符”或者“Tab”作为分隔符。
“-k KEYDEF”:见“2.2.1、‘-k KEYDEF’”。

2.2.1、“-k KEYDEF”

2.2.1.1、选项用途

默认排序时以整行记录作为比较关键词,通过“-k KEYDEF”选项可以自己指定一个或者多个比较关键词。

2.2.1.2、KEYDEF

“KEYDEF”形如“F[.C][b][,F[.C][b]][OPTS]”。
1、第一个“F[.C][b]”
第一个“F[.C][b]”用来指定关键词的起始位置。“F”表示记录中的第“F”个字段(字段从1开始计数);“C”表示该字段中的第“C”个字符(字符从1开始计数),需要注意的是,省略“.C”,等价于“.1”(即表示该字段的第一个字符);“b”选项表示不将字段的前导分隔符作为该字段的一部分,如果不加“b”选项,那么“F.1”指向的其实是第“F”个字段的前导分隔符。
2、第二个“F[.C][b]”
第二个“F[.C][b]”用来指定关键词的结束位置,如果省略,以行结尾作为该关键词的结束位置。“F”表示记录中的第“F”个字段(字段从1开始计数);“C”表示该字段中的第“C”个字符(字符从1开始计数),需要注意的是,省略“.C”,等价于表示该字段的最后一个字符;“b”选项表示不将字段的前导分隔符作为该字段的一部分,如果不加“b”选项,那么“F.1”指向的其实是第“F”个字段的前导分隔符。
3、OPTS
“OTPS”用来指定排序选项,可选值有“dgMhnrf”。注意跟“2.2、选项表示的意思”中的排序选项进行比对。
4、举例
见实验8,9,10,11,12,13。

三、实验

3.1、实验1

有文件“a.txt”,内容如下:

1
2
3
a
d
c

执行sort a.txt命令,得到如下所示结果:

1
2
3
a
c
d

备注:
执行sort -d a.txt命令,得到相同结果。

3.2、实验2

有文件“a.txt”,内容如下:

1
2
3
1.2E10
2.4
01.245

执行sort -g a.txt命令,得到如下所示结果:

1
2
3
01.245
2.4
1.2E10

3.3、实验3

有文件“a.txt”,内容如下:

1
2
3
4
JAN
SEP
DEC
OCT

执行LC_ALL=C sort -M a.txt命令,得到如下所示结果:

1
2
3
4
JAN
SEP
OCT
DEC

注意:
执行命令时加上“LC_ALL=C”是因为在有些语系环境中,“JAN,SEP,DEC,OCT”并不表示月份,故而JAN<SEP<OCT<DEC也不成立。比如执行LC_ALL=zh_CN.utf8 sort -M a.txt命令,得到如下所示结果:

1
2
3
4
DEC
JAN
OCT
SEP

如果将“a.txt”内容改为:

1
2
3
4
06月
07月
12月
01月

此时再执行LC_ALL=zh_CN.utf8 sort -M a.txt命令,就能得到如下所示结果,这符合预期。

1
2
3
4
01月
06月
07月
12月

3.4、实验4

有文件“a.txt”,内容如下:

1
2
3
1G
1K
1M

执行sort -h a.txt命令,得到如下所示结果:

1
2
3
1K
1M
1G

3.5、实验5

有文件“a.txt”,内容如下:

1
2
3
100
0000001
000000001000

执行sort -n a.txt命令,得到如下所示结果:

1
2
3
0000001
100
000000001000

3.6、实验6

有文件“a.txt”,内容如下:

1
2
3
a
b
c

执行sort -r a.txt命令,得到如下所示结果:

1
2
3
c
b
a

3.7、实验7

有文件“a.txt”,内容如下:

1
2
3
4
a
b
B
A

执行sort a.txt命令,得到如下所示结果:

1
2
3
4
a
A
b
B

发现此时有“LC_ALL=zh_CN.utf8”,由此可知在“zh_CN.utf8”语系环境中,字典序中的大小写字母紧邻而列。
再执行LC_ALL=C sort a.txt命令,得到结果如“结果1”所示,由此可知在“C”语系环境中,字典序中的大小写字母非紧邻而列,需要加上“-f”选项,才能达到“使大小写字母紧邻而列”的要求,即执行LC_ALL=C sort -f a.txt命令,执行命令后得到结果如“结果2”所示,这符合预期。

结果1

1
2
3
4
A
B
a
b

结果2

1
2
3
4
A
a
B
b

3.8、实验8

有文件“a.txt”,内容如下:

1
2
3
2 1 1 1
1 2 3 6
3 2 4 5

执行sort a.txt命令(以整行记录内容作为比较关键词),得到如下所示结果:

1
2
3
1 2 3 6
2 1 1 1
3 2 4 5

执行sort -k 2n a.txt命令(从第2个字段前导分隔符开始到行尾为止内容作为比较关键词),得到如下所示结果:

1
2
3
2 1 1 1
1 2 3 6
3 2 4 5

执行sort -k 2,2n -k 4,4n a.txt命令(第一个比较关键词是“从第2个字段前导分隔符开始到第2个字段末尾字符为止内容”,第二个比较关键词是“从第4个字段前导分隔符开始到第4个字段末尾字符为止内容”),得到如下所示结果:

1
2
3
2 1 1 1
3 2 4 5
1 2 3 6

3.9、实验9

有文件“c.txt”,内容如下:

1
2
3
1 R2 a
4 R3 b
3 R10 c

执行sort -k 2.2n c.txt命令(从第2个字段第2个字符开始到行尾为止内容作为比较关键词,“第2个字段第2个字符”实际是3行中的“R”字符,前导分隔符作为字段一部分),得到如下所示结果:

1
2
3
1 R2 a
3 R10 c
4 R3 b

执行sort -k 2.3n c.txt命令(从第2个字段第3个字符开始到行尾为止内容作为比较关键词,3行中的“第2个字段第3个字符”分别是“2”,“3”和“1”,前导分隔符作为字段一部分),得到如下所示结果:

1
2
3
1 R2 a
4 R3 b
3 R10 c

执行sort -k 2.2b,2n c.txt命令(从第2个字段第2个字符开始到第2个字段末尾字符为止内容作为比较关键词,由于加上“b”选项,不将字段前导分隔符作为字段一部分,故而3行中的“第2个字段第2个字符”分别是“2”,“3”和“1”),得到如下所示结果:

1
2
3
1 R2 a
4 R3 b
3 R10 c

3.10、实验10

有文件“a.txt”,内容如下:

1
2
3
4
1 bat 51
2 animal 62
3 check 75
4 car 84

执行LC_ALL=C sort -k 2.1b,2.1b -k 3.2b,3.2bn a.txt命令(第一个比较关键词是“第2个字段的第1个字符”,第二个比较关键词是“第3个字段的第2个字符”,前导分隔符不作为字段一部分),得到如下所示结果:

1
2
3
4
2 animal 62
1 bat 51
4 car 84
3 check 75

3.11、实验11

有文件“a.txt”,内容如下:

1
2
3
4
5
ab1 2ef
cd0 5hi
ef3 4jk
aa3 1cc
bb0 4dd

执行LC_ALL=C sort -k 1.3b,2.1bn a.txt命令(从第1个字段第3个字符开始到第2个字段第1个字符为止内容作为比较关键词,即“比较关键词”横跨两个字段,前导分隔符不作为字段一部分),得到如下所示结果:

1
2
3
4
5
bb0 4dd
cd0 5hi
ab1 2ef
aa3 1cc
ef3 4jk

3.12、实验12

有文件“e.txt”,内容如下:

1
2
3
4
5
6
126 Mar  8 07:45:09 nod1 /sbin/ccccilio[12712]: INFO: sadasdasdas
2 Mar 9 08:16:22 nod1 /sbin/zzzzo[12712]: sadsdasdas
3 JUN 3 10:16:22 nod1 /sbin/hah
1 Mar 8 17:20:01 nod1 /usr/sbin/cron[1826]: asdasdas
4 Mar 9 06:24:01 nod1 /USR/SBIN/CRON[27199]: aaaasdsd
1 Mar 9 06:24:01 nod1 /USR/SBIN/CRON[27201]: aaadas

执行LC_ALL=C sort -k 2b,2bM -k 3b,3bn -k 4b,4b e.txt命令(第一个比较关键词是“第2个字段,不包括前导分隔符”,第二个比较关键词是“第3个字段,不包括前导分隔符”,第三个比较关键词是“第4个字段,不包括前导分隔符”),得到如下所示结果:

1
2
3
4
5
6
126 Mar  8 07:45:09 nod1 /sbin/ccccilio[12712]: INFO: sadasdasdas
1 Mar 8 17:20:01 nod1 /usr/sbin/cron[1826]: asdasdas
1 Mar 9 06:24:01 nod1 /USR/SBIN/CRON[27201]: aaadas
4 Mar 9 06:24:01 nod1 /USR/SBIN/CRON[27199]: aaaasdsd
2 Mar 9 08:16:22 nod1 /sbin/zzzzo[12712]: sadsdasdas
3 JUN 3 10:16:22 nod1 /sbin/hah

以上命令的效果是根据时间排序。

3.13、实验13

有文件“e.txt”,内容如下:

1
2
3
4
5
6
Feb 27 2011 23:05 SOMETHING 2011.02.24.avi
Feb 11 2011 20:06 SOMETHING 2011.02.10.avi
Jan 23 2011 10:42 SOMETHING 2007.12.20.avi
Jan 29 2011 09:17 SOMETHING 2011.01.27.avi
Feb 12 2010 SOMETHING 2010.02.11.avi
Jun 26 2009 SOMETHING 2009.06.25.avi

执行LC_ALL=C sort -k 3b,3bnr -k 1b,1bMr -k 2b,2bnr -k 4b,4br e.txt命令(第一个比较关键词是“第3个字段,不包括前导分隔符”,第二个比较关键词是“第1个字段,不包括前导分隔符”,第三个比较关键词是“第2个字段,不包括前导分隔符”,第四个比较关键词是“第4个字段,不包括前导分隔符”),得到如下所示结果:

1
2
3
4
5
6
Feb 27 2011 23:05 SOMETHING 2011.02.24.avi
Feb 11 2011 20:06 SOMETHING 2011.02.10.avi
Jan 29 2011 09:17 SOMETHING 2011.01.27.avi
Jan 23 2011 10:42 SOMETHING 2007.12.20.avi
Feb 12 2010 SOMETHING 2010.02.11.avi
Jun 26 2009 SOMETHING 2009.06.25.avi

以上命令的效果是根据时间逆序排序。

四、其他

程序实现中使用“LC_COLLATE,LC_ALL,LC_CTYPE”等环境变量,因而最终结果受到“LC_COLLATE,LC_ALL,LC_CTYPE”等环境变量的控制。


参考文献: [1]man sort [2]info sort [3]http://stackoverflow.com/questions/1255782/whats-the-difference-between-general-numeric-sort-and-numeric-sort-options [4]http://stackoverflow.com/questions/12162210/sort-by-just-month-name-and-day-bash [5]http://unix.stackexchange.com/questions/8352/sorting-by-date
您的支持将鼓励我继续分享!