9.sort命令用法

147 阅读5分钟

九.sort

1.命令介绍

sort命令是一个排序命令,可以对文件进行排序,然后将排序结果标准输出。

sort将文件的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出。

2.语法格式及常用选项

依据惯例,我们还是先查看帮助,使用 sort --help

[root@klh ~]# sort --help
用法:sort [选项]... [文件]...
 或:sort [选项]... --files0-from=F
Write sorted concatenation of all FILE(s) to standard output.

Mandatory arguments to long options are mandatory for short options too.
排序选项:
  -b, --ignore-leading-blanks	忽略前导的空白区域
  -d, --dictionary-order	    只考虑空白区域和字母字符
  -f, --ignore-case		       忽略字母大小写
  -g, --general-numeric-sort  compare according to general numerical value
  -i, --ignore-nonprinting    consider only printable characters
  -M, --month-sort            compare (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=KEYDEF          sort via a key; KEYDEF gives location and type
  -m, --merge               merge already sorted files; do not sort
  -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-terminated0 字节而非新行作为行尾标志
      --help		      显示此帮助信息并退出
      --version		      显示版本信息并退出

为了更直观一些,我们把常用的参数用表格来展示:

参数描述
GNU 参数说明
-c检查文件是否按照顺序进行排序
-d排序时,处理英文字母,数字及空格字母外,忽略其他字符
-f排序,将小写字母视为大写字母
-M将前面的3个字母依照月份缩写进行排序
-r以相反的顺序进行排序
-n依照数值的大小进行排序-
-o排序后存入指定的文件
-t指定一个用来区分键位置字符
-k后面跟数字,指定按第几列进行排

有了具体的参数之后,我们再来看实战案例:

3.参考案例
3.1按照文本默认排序

此时,无需加任何参数,sort将文件/文本的每一行作为一个单位,相互比较.

比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出。

[root@klh ~]# sort /etc/passwd |head -5
adm:x:3:4:adm:/var/adm:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
[root@klh ~]# 

从上面的代码可以看到: 按照首字符的ASCII码排序,

这里要理解什么是ASCII码:

在计算机中,所有的数据在存储和运算时都要使用二进制表示。而ASCII是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言,它是现今最通用的单字节编码系统。

英文字母对应的ACSII码如下:
在这里插入图片描述

3.2忽略相同的行

-u参数主要用来忽略相同的行

## 可以看到有相同的行
[root@klh test]# ls
a.txt
[root@klh test]# cat a.txt 
aaa
bbb

ccc
ddd

111
222
444
111
ccc
aaa
## 使用-u参数后
[root@klh test]# sort -u a.txt 删除重复的行,但是空行不会被删除

111
222
444
aaa
bbb
ccc
ddd
[root@klh test]# 

使用-u参数后,相同的行就没有了。

我们之前写过一个脚本统计在线的IP数有多少个,代码如下:

先写一个测试脚本:

[root@klh ~]# vi ping1.sh
[root@klh ~]# cat ping1.sh 
#!/bin/bash
str="192.168.244."
for num in {130..150}
do
ip=${str}${num}
ping -c1 -w1 $ip &>/dev/null

if [ $? -eq 0 ];then
echo $ip >>/root/online.txt

fi
done
# 统计在线IP的个数
online=`cat /root/online.txt|wc -l `
echo "在线ip总数为 $online"

执行上面的脚本查看效果:

[root@klh ~]# sh ping1.sh 
在线ip总数为 2

我们发现执行的结果为12个IP,这个结果是否准确? 我们查看文件内容:

[root@klh ~]# cat online.txt 
192.168.244.131
192.168.244.132

如果发现文件的内容为中有很多重复的IP,这时候我们就可以使用sort -u 参数:

[root@klh ~]# sort -u online.txt |wc -l
4

使用这个命令之后,会感觉IP少了很多,因为去掉了重复的

3.3按数字大小进行排序

此处使用-n 参数

当你使用sort命令对数字进行排序,但是又不用-n参数的时候,就会发现是乱序的:

[root@klh ~]# vi a.txt 
[root@klh ~]# cat a.txt 
aaa
bbb

ccc
ddd

111
22
44
121
ccc
12
aaa
[root@klh ~]# sort a.txt 


111
12
121
22
44
aaa
aaa
bbb
ccc
ccc
ddd

是不是从排序里感觉111 反而不如12大了?

加上-n参数才是正常的,我们来看下代码:

[root@klh ~]# sort a.txt -n


aaa
aaa
bbb
ccc
ccc
ddd
12
22
44
111
121
[root@klh ~]# 

如果向对数字进行倒序排列,需要加-r 参数, 当然这里要对数字排序,所以-n还是少不了的。

[root@klh ~]# sort a.txt -nr
121
111
44
22
12
ddd
ccc
ccc
bbb
aaa
aaa


[root@klh ~]# 
3.4检查文件是否已经按照顺序排序

-c参数,可以检查文件是否按照顺序排序

[root@klh ~]# sort -c a.txt 
sort:a.txt:3:无序:

可以看到无序,表示没有按照顺序排序,这里需要主要,当我们对一个文件排序后,虽然会再屏幕上显示,但并不会修改源文件。

3.5将第3列按照数字大小进行排序

这里用到以下几个参数:

-n是按照数字大小排序
-r是以相反顺序
-k是指定需要排序的栏位
-t指定栏位分隔符为冒号

我们对/etc/passwd 以冒号为分隔符,把第三列进行大小排序

[root@klh ~]# sort -t: -nk 3 /etc/passwd |head -5
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@klh ~]# 

如果我们要将上面的排序变成从大到小排列:

[root@klh ~]# sort -t: -nrk 3 /etc/passwd |head -5
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin

注意:

-t后面可以跟分隔符,如果分割符为: 比如容易操作,但如果分隔符为空格的时候,需要确认空格是否是规则的,比如有的是多个空格,有的是一个空格,就很难达到预期的效果

root@klh ~]# sort -t " " -k 3 b.txt 
9 9 1 0
1 2 3 4 
2 2 4 5 
5 6 7 8 
[root@klh ~]# cat c.txt 
1   2   33   44 
2 2 3 4
7     9   11 4

3 4  6 7

[root@klh ~]# sort -t " " -k 4 c.txt

1   2   33   44 
2 2 3 4
3 4  6 7
7     9   11 4

最后一个的排序按照第四列,就没成功,所以还是那句话,如果空格比较杂乱的时候,不建议使用空格进行排序,如果非要用空格,可以先做预处理。

3.6将排序结果输出到文件

-o参数可以将结果输出到文件,比如我们把3.5的排序输出到a.txt中,原文件内容会被覆盖

[root@klh ~]# sort -t: -nrk 3 /etc/passwd -o a.txt 
[root@klh ~]# cat a.txt 
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
halt:x:7:0:halt:/sbin:/sbin/halt
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
sync:x:5:0:sync:/sbin:/bin/sync
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
root:x:0:0:root:/root:/bin/bash
[root@klh ~]# 
4.探讨 -k的高级用法

案例一: 使用-u 参数去重的时候,希望参照第一个域进行去重

我们知道-u参数是去重,但是必须两行完全重复才可以,而有时候我们根据一部分来去重。

如果我们只用-u去重:

[root@klh ~]# vi d.txt
[root@klh ~]# sort -u d.txt 
klh: 100
klh: 66
klh: 99
lisi:44
wangwu:55
zhangsan: 13
可以看到有三个klh

结合 -k试一下:

[root@klh ~]# sort -t: -u -k 1,1 d.txt 
klh: 100
lisi:44
wangwu:55
zhangsan: 13
[root@klh ~]# 

可以看到klh下面的两个klh被去掉了。

这里的 -k 1,1 我们写作 -k start,end , 如果start 第一个域的第一个字符~end 最后一个域的最后一个字符,如果完全相同,仅保留第一次出现的行,后面出现的相同行都会被消除。

🍻🍻🍻如果你喜欢的话,就不要吝惜你的一键三连了~💕💕💕