Linux文件排序工具 sort 命令详解(6)

[root@linuxidc ~]# echo -e "b 100:200 200\na 110 300" | tr ':' '\0'|sort -t ' ' -k2n b 100200 200 a 110 300

对于"b 100\0200 200"这样的行,"-k 2n"使得该key为"100\0200"。虽然结果看上去是100200,但却只对100进行排序,也就是说它小于110。这就造成了数值排序的假象,100200竟然比110小。

(5).默认情况下,sort会进行一次"最后的排序"。使用"-s"选项将禁止"最后的排序","-u"选项隐含"-s"选项。

考虑这样一种情况:两行在所有key的排序结果上都完全相同,应该如何决定这两行的先后顺序?

例如:

[root@linuxidc ~]# echo -e "b 100 200\na 100 300" | sort -t ' ' -k2n a 100 300 b 100 200

第一行为"b 100 200",第二行为"a 100 300"。由于第2字段都是100,所以这两行在该key上的数值排序的结果相同,于是sort采取最后的手段,完全按照默认规则(即按字符集排序规则升序排序)对整行进行一次排序,这次排序称为"最后的排序"(info sort中称为last-resort comparison)。由于最后的排序过程中,第一个字符a<b,所以最终结果将是第二行"a 100 300"在第一行"b 100 200"的前面。

禁止"最后的排序"后,对那些排序key相同的行,将保留被读取时相对顺序。即,先读取的排在前面。

如果上面的例子中,第二字段不采用数值排序,而是默认排序规则排序呢?如下:

[root@linuxidc ~]# echo -e "b 100 200\na 100 300" | sort -t ' ' -k2 b 100 200 a 100 300

由于默认的排序规则是按照字符集排序规则进行排序,它能识别所有的字符,所以会对"-k2"整个key进行排序,该key会自动扩展为第2字段和第3字段,由于第三字段的2小于3,所以结果中第一行排在第二行的前面。即使如此,sort还是进行了"最后的排序",只不过"最后的排序"不影响排序结果。

如果未指定任何排序选项,其本身就是完全默认的,因此没必要再做最后的排序,所以将不会进行"最后的排序"。如果指定的是"-r"选项,由于"-r"是对最终结果进行反转排序,因此会影响这次的"最后的排序"的结果。

(6).sort的使用建议。

搞清楚了以上几点,是否感觉sort能实现几乎所有的排序需求呢?只要文件够规则,sort就能控制任何一列或多列的排序方式,并且可以设置出是否跨列、跨字符、跨key排序。

这里有几个sort使用建议,算是最后的补充。

任何时候想对单个字段或单个字符排序时,都建议写出POS2,且POS2=POS1,这样能严格排序key的范围只为那个字段或字符。例如,使用"-k2,2"取代"-k2"。

想对多个字段或字符排序时,建议使用多个"-k"选项指定多个key,并按需求为每个key分配私有选项。之所以要如此,是防止无意中忽视了扩展到行尾或者范围。例如,相对第2列、第3列按数值排序,应该指定"-k2n -k3n",而不应该写成"-k2,3n"。

应该总是使用"-b"选项去掉前导空白字符面,防止字段分割时混乱。"-n"隐含了"-b",所以对数值排序时,可以省略"-b"。

对于大文件,建议写出满足需求的所有排序命令,然后使用"-s"关闭"最后的排序"。因为"最后的排序"对每个整行进行排序,性能非常低。 

最后,给出一个测试题:假设一些待排序的日志文件中的内容格式如下:

4.150.156.3 - - [01/Apr/2004:06:31:51 +0000] message 1

211.24.3.231 - - [24/Apr/2004:20:17:39 +0000] message 2

能否理解下面两条等价的命令?

sort -s -t ' ' -k 4.9n -k 4.5M -k 4.2n -k 4.14,4.21 file*.log | sort -s -t '.' -k 1,1n -k 2,2n -k 3,3n -k 4,4n sort -s -t ' ' -k 4.9n -k 4.5M -k 4.2n -k 4.14,4.21 file*.log | sort -s -t '.' -n -k1 -k2 -k3 -k4

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/13538.html