In Unix-like operating systems, sort is a standard command line program that prints the lines of its input or concatenation of all files listed in its argument list in sorted order. Sorting is done based on one or more sort keys extracted from each line of input. By default, the entire input is taken as sort key. Blank space is the default field separator.
The "-r" flag will reverse the sort order.
Syntax
[skypeGNU@localhost ~]$ sort --help
Usage: sort [OPTION]... [FILE]...
or: sort [OPTION]... --files0-from=F
Write sorted concatenation of all FILE(s) to standard output. Mandatory arguments to long options are mandatory for short options too.
Ordering options:
-b, --ignore-leading-blanks ignore leading blanks
-d, --dictionary-order consider only blanks and alphanumeric characters
-f, --ignore-case fold lower case to upper case characters
-g, --general-numeric-sort compare according to general numerical value
-i, --ignore-nonprinting consider only printable characters
-M, --month-sort compare (unknown) < `JAN' < ... < `DEC'
-h, --human-numeric-sort compare human readable numbers (e.g., 2K 1G)
-n, --numeric-sort compare according to string numerical value
-r, --reverse reverse the result of comparisons
Other options:
-k, --key=POS1[,POS2] start a key at POS1 (origin 1), end it at POS2 (default end of line)
-o, --output=FILE write result to FILE instead of standard output
-t, --field-separator=SEP use SEP instead of non-blank to blank transition
-u, --unique with -c, check for strict ordering;
without -c, output only the first of an equal run
sort的工作原理
Sort默认行为是将文件的每一行作为一个单位,相互比较。比较规则是从首字符向后,依次按ASCII码进行比较,最后将其按升序打印到标准输出。
Examples
1、对文件进行升序排序
[skypeGNU@localhost ~]$ cat names.txt
Emma Thomas:100:Marketing
Alex Jason:200:Sales
Madison Randy:300:Product Development
Sanjay Gupta:400:Support
Nisha Singh:500:Sales
Emma Thomas:100:Marketing
[skypeGNU@localhost ~]$ sort names.txt
Alex Jason:200:Sales
Emma Thomas:100:Marketing
Emma Thomas:100:Marketing
Madison Randy:300:Product Development
Nisha Singh:500:Sales
Sanjay Gupta:400:Support
2、-u (--unique) 去掉重复行
[skypeGNU@localhost ~]$ sort -u names.txt
Alex Jason:200:Sales
Emma Thomas:100:Marketing
Madison Randy:300:Product Development
Nisha Singh:500:Sales
Sanjay Gupta:400:Support
3、-r (--reverse) 反转默认的排序方式【默认为升序, 那么-r则为降序】
[skypeGNU@localhost ~]$ cat number.txt
1
3
8
8
5
[skypeGNU@localhost ~]$ sort number.txt
1
3
5
8
8
[skypeGNU@localhost ~]$ sort -r number.txt
8
8
5
3
1
4、-n (--numeric-sort ) 按数值来排序
[skypeGNU@localhost ~]$ cat number.txt
10
3
87
8
5
[skypeGNU@localhost ~]$ sort number.txt
10
3
5
8
87
奇怪吧,因为默认sort是按照字符一个一个比较的。可以强制它compare according to string numerical value
[skypeGNU@localhost ~]$ sort -n number.txt
3
5
8
10
87
5、-t (field-separator)和 -k (--key=POS1[,POS2])选项
在names.txt文件中,有三列:分别是employee_name : employee_id : department_name如果我想按employee_id 排序,如何实现?-t 选项可以指定域分隔符, 而-k 选项则可以指定哪个域。
[skypeGNU@localhost ~]$ sort -n -t':' -k2 names.txt
Emma Thomas:100:Marketing
Emma Thomas:100:Marketing
Alex Jason:200:Sales
Madison Randy:300:Product Development
Sanjay Gupta:400:Support
Nisha Singh:500:Sales
恩, 结果很理想。
5.1、Sorting a tab delimited fileSorting a file with tab
separated values requires a tab character to be specified as the column delimiter. This illustration uses the shell's dollar-quote notation to specify the tab as a C escape sequence.
[skypeGNU@localhost ~]$ sort -t$'\t' -k2 test.txt
"The $'...' string literal syntax was added to ksh93 to solve the problem of entering special characters in scripts. It uses ANSI-C rules to translate the string between the '...'."
有时,遇到像这种表达式: $ sort -k2n,2 -k1,1 quota, 是不是有些匪夷所思。 看例子
[skypeGNU@localhost ~]$ cat test.txt
google 110 5000
baidu 100 5000
guge 50 3000
sohu 100 4500
test.txt格式:第一个域是公司名称,第二个域是公司人数,第三个域是工资
5.2、按照“人数”进行排序,也就是对第二个域排序:
[skypeGNU@localhost ~]$ sort -n -k2 test.txt
guge 50 3000
baidu 100 5000
sohu 100 4500
google 110 5000
虽然结果是正确的, 但是这里有一个问题,那就是 baidu,sohu人数一样,那么sort是如何处理呢? 此时,sort发现有三个相同的域,那么就会按默认方式,从第一个域开始再次进行升序排序。
5.3、按“人数”升序排序,如果“人数”相同,则按“工资”升序排序:
[skypeGNU@localhost ~]$ sort -n -k2 -k3 test.txt
guge 50 3000
sohu 100 4500
baidu 100 5000
google 110 5000
OK, sort支持这种设定,就是说设定域排序的优先级,先以第2个域进行排序,如果相同,再以第3个域进行排序。(如果你愿意,可以一直这么写下去,设定很多个排序优先级)
$ sort -k1,1 -k2 -k3,3n -k4 ....
5.4、按“工资”降序排序,如果“工资”相同,则按“人数”升序排序:
[skypeGNU@localhost ~]$ sort -n -k3r -k2 test.txt
baidu 100 5000
google 110 5000
sohu 100 4500
guge 50 3000
此处有使用了一些小技巧,你仔细看看,在-k 3后面偷偷加上了一个小写字母r。揭晓:r和-r选项的作用是一样的,就是表示逆序。因为sort默认是按照升序排序的,所以此处需要加上r表示第三个域(员工平均工资)是按照降序排序。此处你还可以加上n,就表示仅仅对这个域进行排序时,要按照数值大小进行排序。
6、-k 选项的详细语法要继续往下深入的话,就不得不来点理论知识。
你需要了解-k选项的语法格式,如下:
[ FStart [ .CStart ] ] [ Modifier ] [ , [ FEnd [ .CEnd ] ][ Modifier ] ] F: field C: characterPOS is F[.C][OPTS], where F is the field number and C the character positionin the field; both are origin 1. If neither -t nor -b is in effect, charactersin a field are counted from the beginning of the preceding whitespace. OPTS isone or more single-letter ordering options, which override global orderingoptions for that key. If no key is given, use the entire line as the key.
这个语法格式可以被其中的逗号(“,”)分为两大部分,Start部分和End部分。先给你灌输一个思想,那就是“如果不设定End部分,那么就认为End被设定为行尾”。这个概念很重要的,但往往你不会重视它。Start部分也由三部分组成,其中的Modifier部分就是我们之前说过的类似n和r的选项部分。我们重点说说Start部分的FStart和CStart。
CStart也是可以省略的,省略的话就表示从本域的开头部分开始。之前例子中的-k 2和-k 3就是省略了CStart的例子喽。FStart.CStart,其中FStart就是表示使用的域,而CStart则表示在FStart域中从第几个字符开始算“排序首字符”。同理,在End部分中,你可以设定FEnd.CEnd,如果你省略.CEnd,则表示结尾到“域尾”,即本域的最后一个字符。或者,如果你将CEnd设定为0(零),也是表示结尾到“域尾”。
6.1、从公司名称的第二个字符开始排序
[skypeGNU@localhost ~]$ sort -k1,2 test.txt
baidu 100 5000
google 110 5000
guge 50 3000
sohu 100 4500
-k1,2 就表示对第一个域的第二个字符到本域的最后一个字符为止的字符串进行排序。你会发现baidu因为第二个字母是a而名列榜首。sohu和 google第二个字符都是o,但sohu的h在google的o前面,所以两者分别排在第二和第三。guge只能屈居第四了。
7、关于-k和-u联合使用
[skypeGNU@localhost ~]$ sort -n -k2 test.txt
guge 50 3000
baidu 100 5000
sohu 100 4500
google 110 5000
[skypeGNU@localhost ~]$ sort -n -u -k2 test.txt
guge 50 3000
baidu 100 5000
google 110 5000
当设定以公司员工域进行数值排序,然后加-u后,sohu一行就被删除了!原来-u只识别用-k设定的域,发现相同,就将后续相同的行都删除。
[skypeGNU@localhost ~]$ sort -n -k2 -k3 -u test.txt
guge 50 3000
sohu 100 4500
baidu 100 5000
google 110 5000
咦!这里设置了两层排序优先级的情况下,使用-u就没有删除任何行。原来-u是会权衡所有-k选项,将都相同的才会删除,只要其中有一级不同都不会轻易删除的:)
诡异的排序
[skypeGNU@localhost ~]$ sort -n -k2.2,3.1 test.txt
guge 50 3000
baidu 100 5000
sohu 100 4500
google 110 5000
以第二个域的第二个字符开始到第三个域的第一个字符结束的部分进行排序。
第一行,会提取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前面了。用一个范例即可证实:
[skypeGNU@localhost ~]$ sort -n -k2.2,3.1 -k1,1r test.txt
guge 50 3000
sohu 100 4500
baidu 100 5000
google 110 5000
参考:http://www.cnblogs.com/51linux/archive/2012/05/23/2515299.html