00. 目录
01. 命令概述
sort命令是在Linux里非常有用,它将文件进行排序,并将排序结果标准输出。sort命令既可以从特定的文件,也可以从stdin中获取输入。
02. 命令格式
用法:sort [选项]... [文件]...
- 1
03. 常用选项
长选项必须使用的参数对于短选项时也是必需使用的。
排序选项:
-b, --ignore-leading-blanks 忽略前导的空白区域
-d, --dictionary-order 只考虑空白区域和字母字符
-f, --ignore-case 忽略字母大小写
-g, --general-numeric-sort 按照常规数值排序
-i, --ignore-nonprinting 只排序可打印字符
-M, --month-sort 比较 (未知) < "一月" < ... < "十二月"
在LC_ALL=C 时为(unknown) < `JAN' < ... < `DEC'
-h, --human-numeric-sort 使用易读性数字(例如: 2K 1G)
-n, --numeric-sort 根据字符串数值比较
-R, --random-sort 根据随机hash 排序
--random-source=文件 从指定文件中获得随机字节
-r, --reverse 逆序输出排序结果
--sort=WORD 按照WORD 指定的格式排序:
一般数字-g,高可读性-h,月份-M,数字-n,
随机-R,版本-V
-V, --version-sort 在文本内进行自然版本排序
其他选项:
--batch-size=NMERGE 一次最多合并NMERGE 个输入;如果输入更多
则使用临时文件
-c, --check, --check=diagnose-first 检查输入是否已排序,若已有序则不进行操作
-C, --check=quiet, --check=silent 类似-c,但不报告第一个无序行
--compress-program=程序 使用指定程序压缩临时文件;使用该程序
的-d 参数解压缩文件
--debug 为用于排序的行添加注释,并将有可能有问题的
用法输出到标准错误输出
--files0-from=文件 从指定文件读取以NUL 终止的名称,如果该文件被
指定为"-"则从标准输入读文件名
-k, --key=位置1[,位置2] 在位置1 开始一个key,在位置2 终止(默认为行尾)
参看POS 语法。
-m, --merge 合并已排序的文件,不再进行排序
-o, --output=文件 将结果写入到文件而非标准输出
-s, --stable 禁用last-resort 比较以稳定比较算法
-S, --buffer-size=大小 指定主内存缓存大小
-t, --field-separator=分隔符 使用指定的分隔符代替非空格到空格的转换
-T, --temporary-directory=目录 使用指定目录而非$TMPDIR 或/tmp 作为
临时目录,可用多个选项指定多个目录
--parallel=N 将同时运行的排序数改变为N
-u, --unique 配合-c,严格校验排序;不配合-c,则只输出一次排序结果
-z, --zero-terminated 以0 字节而非新行作为行尾标志
--help 显示此帮助信息并退出
--version 显示版本信息并退出
POS 是F[.C][OPTS],F 代表域编号,C 是域中字母的位置,F 和C 均从1开始计数
如果没有有效的-t 或-b 选项存在,则从前导空格后开始计数字符。OPTS 是一个或多个
由单个字母表示的顺序选项,以此覆盖此key 的全局顺序设置。如果没有指定key 则
将其整个行。
指定的大小可以使用以下单位之一:
内存使用率% 1%,b 1、K 1024 (默认),M、G、T、P、E、Z、Y 等依此类推。
如果不指定文件,或者文件为"-",则从标准输入读取数据。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
04. 参考示例
4.1 将文本默认排序
sort将文件/文本的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出。
[deng@localhost test]$ cat txt
aaa:10:1.1
ccc:30:3.3
ddd:40:4.4
bbb:20:2.2
eee:50:5.5
eee:50:5.5
[deng@localhost test]$ sort txt
aaa:10:1.1
bbb:20:2.2
ccc:30:3.3
ddd:40:4.4
eee:50:5.5
eee:50:5.5
[deng@localhost test]$
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
4.2 忽略相同行
[deng@localhost test]$ sort -u txt
aaa:10:1.1
bbb:20:2.2
ccc:30:3.3
ddd:40:4.4
eee:50:5.5
[deng@localhost test]$
- 1
- 2
- 3
- 4
- 5
- 6
- 7
4.3 忽略每行前面开始出的空格字符
[deng@localhost test]$ sort -b txt
aaa:10:1.1
bbb:20:2.2
ccc:30:3.3
ddd:40:4.4
eee:50:5.5
eee:50:5.5
[deng@localhost test]$
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
4.4 检查文件是否已经按照顺序排序
[deng@localhost test]$ sort -c txt
sort:txt:4:无序: bbb:20:2.2
[deng@localhost test]$
- 1
- 2
- 3
4.5 将第2列按照数字从小到大顺序排列
-n是按照数字大小排序,-r是以相反顺序,-k是指定需要爱排序的栏位,-t指定栏位分隔符为冒号
[deng@localhost test]$ cat txt
AAA:BB:CC
aaa:30:1.6
ccc:50:3.3
ddd:20:4.2
bbb:10:2.5
eee:40:5.4
eee:60:5.1
[deng@localhost test]$ sort -t: -nk 2 txt
AAA:BB:CC
bbb:10:2.5
ddd:20:4.2
aaa:30:1.6
eee:40:5.4
ccc:50:3.3
eee:60:5.1
[deng@localhost test]$
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
4.6 将第3列数字从大到小顺序排列
-n是按照数字大小排序,-r是以相反顺序,-k是指定需要爱排序的栏位,-t指定栏位分隔符为冒号
[deng@localhost test]$ sort -t: -n -r -k 3 txt
eee:40:5.4
eee:60:5.1
ddd:20:4.2
ccc:50:3.3
bbb:10:2.5
aaa:30:1.6
AAA:BB:CC
[deng@localhost test]$
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
4.7 将排序结果输出到源文件
[deng@localhost test]$ sort txt -o sort.txt
[deng@localhost test]$ cat sort.txt
aaa:30:1.6
AAA:BB:CC
bbb:10:2.5
ccc:50:3.3
ddd:20:4.2
eee:40:5.4
eee:60:5.1
[deng@localhost test]$
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
4.8 按照数值的大小排序
[deng@localhost test]$ cat txt
1
10
19
11
2
5
//默认按照字符串排序的结果
[deng@localhost test]$ sort txt
1
10
11
19
2
5
//按照数值大小排序结果
[deng@localhost test]$ sort -n txt
1
2
5
10
11
19
[deng@localhost test]$
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
4.9 -k选项的语法格式
-k选项的语法格式
FStart.CStart Modifie,FEnd.CEnd Modifier
-------Start--------,-------End--------
FStart.CStart 选项 , FEnd.CEnd 选项
- 1
- 2
- 3
这个语法格式可以被其中的逗号,
分为两大部分,Start部分和End部分。Start部分也由三部分组成,其中的Modifier部分就是我们之前说过的类似n和r的选项部分。我们重点说说Start
部分的FStart
和C.Start
。C.Start
也是可以省略的,省略的话就表示从本域的开头部分开始。FStart.CStart
,其中FStart
就是表示使用的域,而CStart
则表示在FStart
域中从第几个字符开始算“排序首字符”。同理,在End部分中,你可以设定FEnd.CEnd
,如果你省略.CEnd
,则表示结尾到“域尾”,即本域的最后一个字符。或者,如果你将CEnd设定为0(零),也是表示结尾到“域尾”。
从公司英文名称的第二个字母开始进行排序
[deng@localhost test]$ sort -t ' ' -k 1.2 txt
baidu 100 5000
sohu 100 4500
google 110 5000
guge 50 3000
[deng@localhost test]$
- 1
- 2
- 3
- 4
- 5
- 6
使用了-k 1.2
,表示对第一个域的第二个字符开始到本域的最后一个字符为止的字符串进行排序。你会发现baidu因为第二个字母是a而名列榜首。sohu和 google第二个字符都是o,但sohu的h在google的o前面,所以两者分别排在第二和第三。guge只能屈居第四了
只针对公司英文名称的第二个字母进行排序,如果相同的按照员工工资进行降序排序
[deng@localhost test]$ sort -t: -k 1.2,1.2 -nrk 3,3 txt
baidu 100 5000
google 110 5000
sohu 100 4500
guge 50 3000
- 1
- 2
- 3
- 4
- 5
由于只对第二个字母进行排序,所以我们使用了-k 1.2,1.2
的表示方式,表示我们“只”对第二个字母进行排序。(如果你问“我使用-k 1.2
怎么不行?”,当然不行,因为你省略了End部分,这就意味着你将对从第二个字母起到本域最后一个字符为止的字符串进行排序)。对于员工工资进行排 序,我们也使用了-k 3,3
,这是最准确的表述,表示我们“只”对本域进行排序,因为如果你省略了后面的3,就变成了我们“对第3个域开始到最后一个域位置的内容进行排序” 了。
4.10 sort其它选项
[deng@localhost test]$ cat txt
google 110 5000
baidu 100 5000
guge 50 3000
sohu 100 4500
[deng@localhost test]$
- 1
- 2
- 3
- 4
- 5
- 6
第一个域是公司名称,第二个域是公司人数,第三个域是员工平均工资。
公司的字母顺序排序
[deng@localhost test]$ sort -t ' ' -k 1 txt
baidu 100 5000
google 110 5000
guge 50 3000
sohu 100 4500
[deng@localhost test]$
- 1
- 2
- 3
- 4
- 5
- 6
按照公司人数排序
[deng@localhost test]$ sort -t ' ' -n -k 2 txt
guge 50 3000
baidu 100 5000
sohu 100 4500
google 110 5000
- 1
- 2
- 3
- 4
- 5
不用解释,我相信你能懂。但是,此处出现了问题,那就是baidu和sohu的公司人数相同,都是100人,这个时候怎么办呢?按照默认规矩,是从第一个域开始进行升序排序,因此baidu排在了sohu前面。
按照公司人数排序 ,人数相同的按照员工平均工资升序排序
[deng@localhost test]$ sort -t ' ' -n -k 2 -k 3 txt
guge 50 3000
sohu 100 4500
baidu 100 5000
google 110 5000
[deng@localhost test]$
- 1
- 2
- 3
- 4
- 5
- 6
看,我们加了一个-k2 -k3就解决了问题。对滴,sort支持这种设定,就是说设定域排序的优先级,先以第2个域进行排序,如果相同,再以第3个域进行排序。(如果你愿意,可以一直这么写下去,设定很多个排序优先级)
按照员工工资降序排序,如果员工人数相同的,则按照公司人数升序排序
[deng@localhost test]$ sort -n -t ' ' -k 3r -k 2 txt
baidu 100 5000
google 110 5000
sohu 100 4500
guge 50 3000
[deng@localhost test]$
- 1
- 2
- 3
- 4
- 5
- 6
此处有使用了一些小技巧,你仔细看看,在-k 3后面偷偷加上了一个小写字母r。揭晓:r和-r选项的作用是一样的,就是表示逆序。因为sort默认是按照升序排序的,所以此处需要加上r表示第三个域(员工平均工资)是按照降序排序。此处你还可以加上n,就表示对这个域进行排序时,要按照数值大小进行排序,举个例子吧:
[deng@localhost test]$ sort -t ' ' -k 3nr -k 2n txt
baidu 100 5000
google 110 5000
sohu 100 4500
guge 50 3000
[deng@localhost test]$
- 1
- 2
- 3
- 4
- 5
- 6
我们去掉了最前面的-n选项,而是将它加入到了每一个-k选项中了。
从公司英文名称的第二个字母开始进行排序
[deng@localhost test]$ sort -t ' ' -k 1.2 txt
baidu 100 5000
sohu 100 4500
google 110 5000
guge 50 3000
[deng@localhost test]$
- 1
- 2
- 3
- 4
- 5
- 6
对公司英文名称的第二个字母进行排序,如果相同的按照员工工资进行降序排序
[deng@localhost test]$ sort -t ' ' -k 1.2,1.2 -k 3,3nr txt
baidu 100 5000
google 110 5000
sohu 100 4500
guge 50 3000
[deng@localhost test]$
- 1
- 2
- 3
- 4
- 5
- 6
05. 附录
5、KV存储部件对应UtilsFile接口部分的代码
分析下KV存储部件对应UtilsFile接口部分的代码。我们知道对外接口有设置键值UtilsSetValue、获取键值UtilsGetValue、删除键值UtilsDeleteValue和清除缓存ClearKVCache。我们先看看内部接口,这些接口调用的全部是UtilsFile接口,没有使用POSIX的文件接口。
5.1 内部接口
5.1.1 GetValueByFile和SetValueToFile从文件中读写键值
函数GetValueByFile用于从文件中读取键值,⑴处获取键名对应的键值文件的大小,如果文件大于等于参数中指定的长度len,返回EC_FAILURE。等于也不行,末尾需要放置一个空字符。⑵处打开文件,然后读取文件,读取的内容放入变量value里。⑶处末尾添加null空字符,然后返回获取的字符的长度。函数SetValueToFile用于把键值保存到文件里,⑷处调用UtilsFile接口打开,然后写入到文件里。
static int GetValueByFile(const char* key, char* value, unsigned int len)
{
unsigned int valueLen = 0;
⑴ if (UtilsFileStat(key, &valueLen) != EC_SUCCESS) {
return EC_FAILURE;
}
if (valueLen >= len) {
return EC_FAILURE;
}
⑵ int fd = UtilsFileOpen(key, O_RDONLY_FS, 0);
if (fd < 0) {
return EC_FAILURE;
}
int ret = UtilsFileRead(fd, value, valueLen);
UtilsFileClose(fd);
fd = -1;
if (ret < 0) {
return EC_FAILURE;
}
⑶ value[valueLen] = '\0';
return valueLen;
}
static int SetValueToFile(const char* key, const char* value)
{
⑷ int fd = UtilsFileOpen(key, O_RDWR_FS | O_CREAT_FS | O_TRUNC_FS, 0);
if (fd < 0) {
return EC_FAILURE;
}
int ret = UtilsFileWrite(fd, value, strlen(value));
UtilsFileClose(fd);
fd = -1;
return (ret < 0) ? EC_FAILURE : EC_SUCCESS;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
评论记录:
回复评论: