日期:2014-05-16  浏览次数:20864 次

Linux sort命令的几个细节问题

        Linux sort命令的原理是逐行按字符进行比较排序,当然,也可以通过命令行参数设定按数字进行比较,或者指定行间的分隔符,对某一个或一些字段按照自己指定的规则进行排序。这是一个很常用而且很方便的命令,但是其中的一些细节需要注意,否则会得到错误的排序结果。

1. 比较方式

        前面说过,sort命令默认是按照字符串排序,真的是这样么?看看sorthelp信息,末尾有这样的文字:

*** WARNING ***
The locale specified by the environment affects sort order.
Set LC_ALL=C to get the traditional sort order that uses
native byte values.

        看来,环境变量也能影响sort的排序结果。实际试试看:

~$ cat text
11$
1{1
~$ sort text
1{1
11$
~$ echo $LC_ALL
~$

        论ASCII字符的大小,’{’应该比’1’大,但是上面的结果显示,当LC_ALL变量为空值时,sort命令输出了错误的排序结果。不过,在更多的平台上实验发现,LC_ALL为空的时候并不一定会输出这个错误的结果,具体原因不详。不过,如果按照sort的帮助信息设置LC_ALL,则结果是正确的,’1’排在’{’前面。

        如果了解LC***系列的变量,其实只需要设置LC_COLLATE即可,该变量控制的是字符串的排序方式,在手头上的几种平台上实验,结果都是正确的。

2. 按数字排序

        加-n参数按数字排序。如果一行中还有非数字字符,则按照非数字字符前面的数字大小进行排序。

~$ cat text
11$
1{1
~$ export LC_ALL=C
~$ sort text
11$
1{1
~$ sort -n text      
1{1
11$

3. 重定向

        一般sort命令将排序结果输出到终端,如果想写入文件可以用重定向的方式,但是,如果想让排序结果直接写到排序前的文件,用一般的重定向方式sort file_name > file_name达不到效果,需要用sort命令的-o参数。

4. 分隔字段

        默认的排序是以行为单位的排序,如果想按照某个字段进行排序,可以用-t选项指定字段分隔符,-k指定要排序的字段。

        -k参数的格式为-k start[,end],需要注意的是,如果省略了end,则需要比较到行末,例如:

~$ cat text 
1|101|2
1|10|2
~$ echo $LC_ALL
C
~$ sort -t "|" -k 2 text 
1|101|2
1|10|2
~$ sort -t "|" -k 2,2 text 
1|10|2
1|101|2

        虽然10排在101前面,但是不指定字段结束时,默认会继续比较,即比较’|’和’1’,所以有上面的结果。

        通常,我们只希望按照一个或者多个字段排序,而不希望从某个字段开始一直比较到行