目录
33. shell命令--sort
功能说明
sort 是 Linux 和 Unix 系统中的一个常用命令,用于对文本文件的行进行排序。
sort 命令的功能是对文件内容进行排序。有时文本中的内容顺序不正确,一行行地手动修改实在太麻烦了。此时使用 sort 命令就再合适不过了,它能够对文本内容进行再次排序。
语法格式
SYNOPSIS
sort [OPTION]... [FILE]...
sort [OPTION]... --files0-from=F
选项说明
-b, --ignore-leading-blanks:忽略每行前的空格字符。
-c, --check, --check=diagnose-first:检查输入是否已排序;如果不排序,则报告第一个失序行。
-C, --check=quiet, --check=silent:似于 -c 选项,但不输出第一个未排序的行。
-d, --dictionary-order:仅考虑空白、字母和数字字符,忽略其他字符。
-f, --ignore-case:忽略大小写。
-g, --general-numeric-sort:按数值比较,忽略空格和逗号等。
-h, --human-numeric-sort:按人类可读的数字(如 2K 1G)排序。
-i, --ignore-nonprinting:考虑不可打印字符。
-k,--key=KEYDEF,POS1[,POS2]:根据指定的字段位置进行排序。例如,-k 2,2n 表示按第二列进行数值排序。
-m, --merge:合并已排序的文件。
-M, --month-sort:按月份名排序(如 JAN, DEC)。
-n, --numeric-sort:按数值进行排序。
-o FILE, --output=FILE:将结果写入 FILE 而不是标准输出。
-r, --reverse:逆序排序。
-R, --random-sort:随机排序(依据随机哈希值),但分组相同的行。
-s, --stable:在排序后保留相同的行的原始顺序(稳定排序)。
-t CHAR, --field-separator=CHAR:使用 CHAR 代替空格或制表符作为字段分隔符。
-T, --temporary-directory=DIR:使用DIR作为临时目录,而不是 $TMPDIR 或 /tmp;多次使用该选项指定多个临时目录。
-u, --unique:仅输出唯一的行(相当于 uniq)。
-v, --version:显示版本信息。
-z, --zero-terminated:以空字符(null)结束行,而不是换行符。
--sort=WORD:根据WORD排序,其中: general-numeric 等价于 -g,human-numeric 等价于 -h,month 等价于 -M,numeric 等价于 -n,random 等价于 -R,version 等价于 -V。
--compress-program=PROG:使用PROG压缩临时文件;使用PROG -d解压缩。
--debug:注释用于排序的行,发送可疑用法的警报到stderr。
--files0-from=F:从文件F中读取以NUL结尾的所有文件名称;如果F是 - ,那么从标准输入中读取名字
--parallel=N:将并发运行的排序数更改为N。
KEYDEF的格式为:F[.C][OPTS][,F[.C][OPTS]] ,表示开始到结束的位置。
F表示列的编号
C表示OPTS为[bdfgiMhnRrV]中的一到多个字符,用于覆盖当前排序选项。
使用--debug选项可诊断出错误的用法。
SIZE 可以有以下的乘法后缀:
% 内存的1%;
b 1;
K 1024(默认);
剩余的 M, G, T, P, E, Z, Y 可以类推出来。
返回值
返回0表示成功,返回非0值表示失败。
实践操作
0. 环境准备
mkdir -p /test/sort
cd /test/sort
cat >file1.txt <<'eof'
aaa:10:1.1
ccc:30:3.3
ddd:40:4.4
bbb:20:2.2
eee:50:5.5
eee:50:5.5
eof
cat >file2.txt <<'eof'
No1:No2:No3
aaa:30:1.6
ccc:50:3.3
ddd:20:4.2
bbb:10:2.5
eee:40:5.4
eee:60:5.1
eof
cat >file3.txt <<'eof'
4
2
1
3
eof
head -v file*
1. 按默认方式排序
cat file1.txt
sort file1.txt
2. 忽略相同行使用 -u 选项或者 uniq
cat file1.txt
sort file1.txt
sort -u file1.txt
uniq file1.txt
3. sort的-n、-r、-k、-t选项的使用
3.1 将 No2 列按照数字从小到大顺序排列
cat file2.txt
sort file2.txt
sort -nk 2 -t: file2.txt
3.2 将 No3 列数字从大到小顺序排列:
# -n是按照数字大小排序,-r是以相反顺序,
# -k是指定需要排序的栏位,-t指定栏位分隔符为冒号号
cat file2.txt
sort -nrk 3 -t: file2.txt
4. 忽略每行前的空格,按数值排序
cat file3.txt
sort -b file3.txt #-b 忽略每行前的空格字符
sort -bn file3.txt #-n 按数值进行排序
5. 忽略每行前的逗号,按数值排序
echo -e ",6\n ,5" >>file3.txt
cat file3.txt
sort -b file3.txt
sort -bn file3.txt
sort -bd file3.txt #-d 仅考虑空白、字母和数字字符,忽略其他字符
6. 再试下逆序排序
cat file3.txt
sort file3.txt
sort -r file3.txt
sort -brd file3.txt
7. 将结果写入另一个文件
sort -bd file3.txt
sort -bd file3.txt -o sorted_file1.txt
cat sorted_file1.txt
sort -brd file3.txt > sorted_file2.txt
cat sorted_file2.txt
注意事项
关于-k选项的解读和例子:
-k选项深度解读:
FStart.CStart Modifier,FEnd.CEnd Modifier
-------Start--------,-------End--------
FStart.CStart 选项 , FEnd.CEnd 选项
这个语法格式可以被其中的逗号,分为两大部分,Start 部分和 End 部分。 Start 部分由三部分组成,其中的 Modifier 部分就是我们之前说过的选项部分; 我们重点说说 Start 部分的 FStart 和C.Start;C.Start 是可以省略的,省略的话就表示从本域的开头部分开始。FStart.CStart,其中 FStart 就是表示使用的域,而 CStart 则表示在 FStart 域中从第几个字符开始算排序首字符。 同理,在 End 部分中,你可以设定 FEnd.CEnd,如果你省略 .CEnd 或将它设定为 0,则表示结尾到本域的最后一个字符。
例子:从公司英文名称的第二个字母开始排序:
$ sort -t ' ' -k 1.2 facebook.txt
baidu 100 5000
sohu 100 4500
google 110 5000
guge 50 3000
解读:使用了-k 1.2,表示对第一个域的第二个字符开始到本域的最后一个字符为止的字符串进行排序。你会发现baidu因为第二个字母是a而名列榜首。sohu 和 google 第二个字符都是 o,但 sohu 的 h在 google 的 o 前面,所以两者分别排在第二和第三。guge 只能屈居第四了。
例子:只针对公司英文名称的第二个字母进行排序,如果相同的按照员工工资进行降序排序:
$ sort -t ' ' -k 1.2,1.2 -nrk 3,3 facebook.txt
baidu 100 5000
google 110 5000
sohu 100 4500
guge 50 3000
解读:由于只对第二个字母进行排序,所以我们使用了 -k 1.2,1.2 的表示方式,表示我们只对第二个字母进行排序(如果你问我使用 -k 1.2 怎么不行?当然不行,因为你省略了 End 部分,这就意味着你将对从第二个字母起到本域最后一个字符为止的字符串进行排序)。 对员工工资进行排序,我们也使用了 -k 3,3,这是最准确的表述,表示我们只对本域进行排序,因为如果你省略了后面的 3,就变成了我们对第 3 个域开始到最后一个域位置的内容进行排序了。
注意
- 关于-g和-n选项的区别:stackoverflow
- 关于这个复杂命令的学习,建议您阅读info文档及参考博客、问答网站等。
- 该命令是GNU coreutils包中的命令,相关的帮助信息请查看man -s 1 shuf,info coreutils 'shuf invocation'。