介绍
作用
Linux sort 命令用于将文本文件内容加以排序。
sort 可针对文本文件的内容,以行为单位来排序。
注意
1、排序时,默认是按每行/每个域的首字符排序,数字的优先级要大于字符的优先级
2、不指定升序还是降序时,默认是升序
语法
|
|
参数
- -b 忽略每行前面开始出的空格字符。
- -c 检查文件是否已经按照顺序排序。
- -d 排序时,处理英文字母、数字及空格字符外,忽略其他的字符。
- -f 排序时,将小写字母视为大写字母。
- -i 排序时,除了040至176之间的ASCII字符外,忽略其他的字符。
- -m 将几个排序好的文件进行合并。
- -M 将前面3个字母依照月份的缩写进行排序。
- -n 依照数值的大小排序。
- -u 意味着是唯一的(unique),输出的结果是去完重了的。
- -o<输出文件> 将排序后的结果存入指定的文件。
- -r 以相反的顺序来排序。
- -t<分隔字符> 指定排序时所用的栏位分隔字符。
- +<起始栏位>-<结束栏位> 以指定的栏位来排序,范围由起始栏位到结束栏位的前一栏位。
- –help 显示帮助。
- –version 显示版本信息。
- [-k field1[,field2]] 按指定的列进行排序。
重点掌握
|
|
实例
-r,逆序排序
数据准备
|
|
|
|
实验
如下所示,单独使用sort命令对文件内容进行排序,默认情况按照第一列字段内容的首字母进行升序排序
|
|
|
|
使用-r选项可按照逆序排序,但排序依据仍旧默认是第一列字段内容的首字母
|
|
|
|
-k,指定按照某列进行排序
我们先使用salary.txt文本内容进行实验,输入以下命令
|
|
观察输出结果可以发现,目前的排序结果是按照第二列字段的内容进行升序排序的
|
|
但这个结果其实只是一个巧合,为什么这么说呢?我们看接下来的实验
-n,按照数值大小排序
数据准备
|
|
|
|
我们看使用 nums.txt 文件内容的第二列进行排序的结果
|
|
观察实验结果,我们看到
- 我们期望的是能够按照 nums.txt 的第二列内容进行升序排序
- 但实际情况是,出现了数字10排列在数字2之前的结果
|
|
出现这个结果的原因也很简单,因为默认情况下,sort命令是将文本按照字符串进行排序的,举个例子,上述数字“10”和数字“2”,
- 它直接将这两个数字按照字符串处理
- 于是字符串“10”的第一个字符是“1”,而字符串“2”的第一个字符是2
- 字符“1”比字符“2”小,因为sort只按照首字符进行排序,因此最后的结果就变成了“10”比“2”小
|
|
上述命令的意思是,让sort将第二列内容视为数值,并以此为依据进行升序排序,观察实验结果这次是符合预期的
|
|
同样的,我们也可以将其按照降序排序,如下所示
|
|
|
|
-t,指定字段分隔符
该选项的作用是指定字段分隔符
数据准备
|
|
|
|
实验
我们首先不指定分隔符,想让内容按照第二列数据,也就是按照年龄进行升序排序,查看结果
|
|
可以看到,下述的输出结果也是不符合我们预期的,这又是为什么呢?
|
|
造成这个结果的原因是,
- 当我们想使用-k选项找到第二列,它首先需要知道文本是按照什么分割符划分第一列第二列
- 我们文件内容的每一行的每一列都是按照逗号进行分割的,sort命令不知道这一点
- 默认情况下,sort默认使用空格或者制表符作为分隔符,因此它此时找到的第二列是一个空列,也就是每一行的末尾
因此,这就是-t选项的作用,让sort知道我们的文本是按照什么分割符进行划分的,好让-k选项真正生效
重新输入命令
|
|
|
|
可以看到,这次的输出结果是符合预期的
练习,组合命令的使用
到这里,我们先写一道题,熟悉一下上述学过的命令
题目:在salary中,按薪水进行降序排列,薪资相同时,按公司人数升序排列。
首先回顾一下我们的salary.txt文本内容,如下,第二列数据表示公司人数,第三列数据表示公司薪水
|
|
我们直接给出答案,然后进行分析
|
|
输出结果
|
|
首先说明,这个输出结果是符合预期的,那么为什么要这么写
在此需要指出
- -n是全局参数,所有指定的域(列)都有效(按数值排序)
- 3r中的紧跟这数字的r是局部参数,仅对-k 3r中r前面的数字所对应的第3个域(列)有效
- 后面的 -k 2 没有指定降序,那么默认第2个域(列)就是升序排列的。
-o,把结果输出到指定文件
在sort排序中,如果用 > 重定向来把结果输出到源文件,源文件会被置为空。
此时,-o的作用就凸显出来了。
我们先备份一下数据进行实验
|
|
输入以下命令,我们期望的结果是,让文件按照第二列进行排序,并将排序的结果保存起来
|
|
但现实情况是,此时的s.txt文件被置空了,也就是说,如果要把排序的结果回写到源文件,需要用-o参数,不能用重定向。
如果需要保存排序的结果,正确的命令应该是
|
|
-u 去除重复行 | -k M,N消除指定域的重复行
再次回顾我们的salary.txt文件内容,我们看到,文本中有三条sohu相关的行,我们现在的需求是,我们想去除重复的行
|
|
首先尝试使用下述命令
|
|
实验失败
|
|
如果我们显示指定列呢?也就是这样
|
|
还是失败!为什么呢?
|
|
这是因为,sort排序的时候,****-u不配合其他任何参数**时,只有*完全相同的重复行*才会被消除。
另外还需要给出一个知识点,关于**-k选项,其实是有两个参数的**,这个两个参数指定了一个范围
-K M,N
M的意思是,从哪一列开始的第一个字符作为比较的依据;N表示截止到哪一列的最后一个字符比较结束。
M,N是一个(域的)范围,如果这个M,N结合-u使用。那么-u的比较范围就是第M列的第一个字符到第N列最后一个字符之间的这段内容。
如果数字N被省略,那么-u比较的范围就是从M域开始,一直到每行的最后一个域的最后一个字符。
因此,正确的命令应该如下,这条命令是说,从第一列的第一个字符开始,到第一列的最后一个字符进行检查,如果发现重复就去重
|
|
|
|
-k 的高级用法-k1.2,3.5
通过上一案例的学习,对-k M,N有了一定了解,接下来的内容相对会比较容易理解一些。
理论知识点:
如果抛开M,N之间的逗号,单独说这个逗点
- -k 1.2 表示第1个列的第二个字符
- -k 2.3 表示从第2个列的第三个字符。
案例:仅仅按工资表中第一列的第二个字符升序排列
错误示范
|
|
|
|
正确示范
|
|
|
|
解析
- -k1.2,1.2 仅仅且只按照第一个域的第二个字母进行排序,不会再按其他字符进行排序。
- -k1.2 先按照第一个域的第二个字母进行排序,第二个字母如果一样,再按照第二个字母后面的字母进行排序,依次类推,直到行尾最后一个字符。也就是说:google 和 sohu的第二个字母都是o,就开始看第三个字母,显然第三个字母h应该排在o的前面。