《LINUX实操:Linux文件排序工具 sort 命令详解》要点:
本文介绍了LINUX实操:Linux文件排序工具 sort 命令详解,希望对您有用。如果有疑问,可以联系我们。
本文目次:
1.1 选项阐明
1.2 sort示例
1.3 深刻研究sort
sort是排序工具,它完美贯彻了Unix哲学:”只做一件事,并做到完美”.它的排序功能极强、极完整,只要文件中的数据足够规则,它几乎可以排出所有想要的排序成果,是一个非常优质的工具.
虽然sort很强大,但它的选项很少,使用办法也很简单.更让人觉得它成功的地方在于:即使想要实现复杂、完整的sort功能,所使用的选项和一般使用时的选项没什么不同.只不过要实现复杂功能时,必须得理解sort是如何工作的.
也便是说,没搞懂sort工作机制时,它也能完成任务,指哪就能打哪,但没被指到的地方难免会有所偏差和疑惑.只有搞懂了sort机制,才能真正的指哪打哪,结果中一丝偏差也没有,即使出现了偏差也知道是为什么.
本文先解释sort命令的常用选项,再给出sort的简单使用示例,用于初步解释sort各选项,最后对sort深入阐明.更完整的选项阐明可参考info sort的译文:sort命令中文手册(info sort翻译).
1.1 选项说明
sort读取每一行输入,并依照指定的分隔符将每一行划分成多个字段,这些字段就是sort排序的对象.同时,sort可以指定依照何种排序规则进行排序,如依照当前字符集排序规则(这是默认排序规则)、依照字典排序规则、依照数值排序规则、依照月份排序规则、依照文件大小格式(k<M<G).还可以去除重复行,指定降序或升序(默认)的排序方式.
默认的排序规则为字符集排序规则,通常几种常见字符的次序为:”空字符串<空白字符<数值<a<A<b<B<…<z<Z”,字典排序规则也如此.
语法格局:
sort [OPTION]... [FILE]... 选项说明: -c:检测给定的文件是否已经已经排序.如未排序,则会输出诊断信息,提示从哪一行开始乱序. -C:类似于"-c",只不过不输出任何诊断信息.可以通过退出状态码1判断出文件未排序. -m:对给定的多个已排序文件进行合并.在合并过程中不做任何排序动作. -b:忽略字段的前导空白字符.空格数量不固定时,该选项几乎是必须要使用的."-n"选项隐含该选项. -d:依照字典顺序排序,只支持字母、数值、空白.除了特殊字符,一般情况下基本等同于默认排序规则. --debug:将显示排序的过程以及每次排序所使用的字段、字符.同时还会在最前几行显示额外的信息. -f:将所有小写字母当成大写字母.例如,"b"和"B"是相同的. :在和"-u"选项一起使用时,如果排序字段的比较结果相等,则丢弃小写字母行. -k:指定要排序的key,key由字段组成.key格式为"POS1[,POS2]",POS1为key起始位置,POS2为key结束位置. -n:按数值排序.空字符串""或"\0"被当作空.该选项除了能识别负号"-",其他所有非数字字符都不识别. :当按数值排序时,遇到不识别的字符时将立即结束该key的排序. -M:按字符串格式的月份排序.会自动转换成大写,并取缩写值.规则:unknown<JAN<FEB<...<NOV<DEC. -o:将结果输出到指定文件中. -r:默认是升序排序,使用该选项将得到降序排序的结果. :注意:"-r"不参与排序动作,只是操作排序完成后的结果. -s:禁止sort做"最后的排序". -t:指定字段分隔符. :对于特殊符号(如制表符),可使用类似于-t$'\t'或-t'ctrl+v,tab'(先按ctrl+v,然后按tab键)的方法实现. -u:只输出重复行的第一行.结合"-f"使用时,重复的小写行被丢弃.
1.2 sort示例
此小节为sort的简单用法示例,也是平时最可能用上的示例.如果只是为了使用sort,而不是为了刨根问题,本小节已经足够.
假设当前已有文件system.txt,内容如下:其中空白部门为单个制表符.
(1).不加任何选项时,将对整行从第一个字符开始依次向后直到行尾依照默认的字符集排序规则做升序排序.
[root@linuxidc tmp]# sort system.txt 1 mac 2000 500 2 winxp 4000 300 3 bsd 1000 600 4 linux 1000 200 5 SUSE 4000 300 6 Debian 600 200
由于每行的第一个字符1<2<3<4<5<6,所以成果如上.
(2).以第三列为排序列进行排序.由于要划分字段,以是指定字段分隔符.指定制表符这种无法直接输入的特殊字符的方式是$’\t’.
[root@linuxidc tmp]# sort -t $'\t' -k3 system.txt 4 linux 1000 200 3 bsd 1000 600 1 mac 2000 500 2 winxp 4000 300 5 SUSE 4000 300 6 Debian 600 200
结果中虽然1000<2000<4000的顺序是对了,但600却排在最后面,因为这是依照默认字符集排序规则进行排序的,字符6大于4,所以排最后一行.
(3).对第三列按数值排序规矩进行排序.
[root@linuxidc tmp]# sort -t $'\t' -k3 -n system.txt 6 Debian 600 200 3 bsd 1000 600 4 linux 1000 200 1 mac 2000 500 2 winxp 4000 300 5 SUSE 4000 300
成果中600已经排在第一行.成果中第2行、第3行的第三列值均为1000,如何决定这两行的顺序?
(4).在对第3列按数值排序规则排序的根基上,使用第四列作为决胜属性,且是以数值排序规则对第四列排序.
[root@linuxidc tmp]# sort -t $'\t' -k3 -k4 -n system.txt 6 Debian 600 200 4 linux 1000 200 3 bsd 1000 600 1 mac 2000 500 2 winxp 4000 300 5 SUSE 4000 300
如果想在第3列按数值排序后,以第2列作为决胜列呢?由于第2列为字母而非数值,所以下面的语句是差错的,虽然得到了期望的结果.
[root@linuxidc tmp]# sort -t $'\t' -k3 -k2 -n system.txt 6 Debian 600 200 3 bsd 1000 600 4 linux 1000 200 1 mac 2000 500 2 winxp 4000 300 5 SUSE 4000 300
之所以最终得到了正确的结果,是因为默认情况下,在命令行中指定的排序行为结束后,sort还会做最后一次排序,这最后一次排序是对整行依照完全默认规则进行排序的,也就是按字符集、升序排序.由于1000所在的两行中的第一个字符3小于4,所以3排在前面.
之所以说上面的语句是错误的,是因为第2列第一个字符是字母而不是数值,在按数值排序时,字母是不可辨认字符,一遇到不可辨认字符就会立即结束该字段的排序行为.可以使用”–debug”选项来查看排序的过程和排序时所使用的列.注意,该选项只有CentOS 7上的sort才有.
[root@linuxidc tmp]# sort --debug -t $'\t' -k3 -k2 -n system.txt sort: using ‘en_US.UTF-8’ sorting rules sort: key 1 is numeric and spans multiple fields sort: key 2 is numeric and spans multiple fields 6>Debian>600>200 ___ # 第1次排序行为,即对"-k3"排序,此次用于排序的字段为第3列 ^ no match for key # 第2次排序行为,即对"-k2"排序,但显示无法匹配排序key ________________ # 默认sort总会进行最后一次排序,排序对象为整行 3>bsd>1000>600 ____ ^ no match for key ______________ 4>linux>1000>200 ____ ^ no match for key ________________ 1>mac>2000>500 ____ ^ no match for key ______________ 2>winxp>4000>300 ____ ^ no match for key ________________ 5>SUSE>4000>300 ____ ^ no match for key _______________
(5).在对第3列按数值排序规则排序的根基上,使用第2列作为决胜属性,且以默认排序规则对此列降序排序.
[root@linuxidc tmp]# sort -t $'\t' -k3n -k2r system.txt 6 Debian 600 200 4 linux 1000 200 3 bsd 1000 600 1 mac 2000 500 2 winxp 4000 300 5 SUSE 4000 300
由于既要对第3列按数值升序排序,又要对第2列按默认规则降序排序,因此只能对每个字段单独分配选项.注意,虽然”r”选项是降序结果,但它不影响排序过程,只影响最终排序结果.也就是说,在依照升序排序结束得到最终结果后,再反转第2列顺序,也就是得到了降序的结果.同样也说明,sort在排序的时候,一定且只能依照升序排序,只有排序动作结束了”r”选项才开始工作.
紧跟在字段后的选项(如”-k3n”的”n”和”-k2r”的”r”)称为私有选项,使用短横线写在字段外的选项(如”-n”、”-r”)为全局选项.当没有为字段分配私有选项时,该排序字段将继承全局选项.当然,只有像”-n”、”-r”这样的排序性的选项能力继承和分配给字段,”-t”这样的选项则无法分配.
是以,”-n -k3 -k4″、”-n -k3n -k4″和”-k3n -k4n”是等价的,”-r -k3n -k4″和”-k3nr -k4r”是等价的.
实际上,上面的命令写法并不严谨.更尺度的写法应该如下:
sort -t $'\t' -k3n -k2,2r system.txt
“-k2,2″表示排序对象从第2个字段开始到第2个字段结束,也便是限定了只对第二个字段排序.它的格式为”POS1,POS2″,如果省略POS2,将自动扩展到行尾,即”-k2″等价于”-k2,4″,也便是说,对整个第2列到第4列进行排序.
需要注意,由于上面的”-k2″继承了全局默认的排序规则,即按字符排序而非按数值排序,此时它能够等价于”-k2,但如果是”-k2n”依照数值排序的话,它不等价于”-k2,4n”或”-k2n,4″(这3者为等价写法),之所以不等价,是因为按数值排序时只能识别数字和负号”-“,当排序时遇到其他所有字符,都将立即结束此次排序.所以”-k2n”等价于”-k2,2n”或”-k2n,2″或”-k2n,2n”.
这些理论性的知识点,请参照下一小节sort的理论内容.后文也不再解释理论性的内容,只是介绍命令使用办法.