Skip to content
On this page

总结

  • ps -ef: 显示所有程序,结合 sort -k 排序目前 CPU 或 内存占用情况
  • top: 更好用的监控系统资源占用情况,P CPU 排序,M 内存排序
  • sort [File...]: 默认按第一列字符 ASCII 排序。可以多个文件内容一块排序
    • -r: 降序排序
    • -k x,x: 按列排序,显性设定 End 在同一列,符合我们的惯性思维。
    • -t: 指定分隔符
    • -n: 按数字大小排序

需要留意,如果 sort -k x 未指明 End,排序内容为起始点到行末,排序时并没有列的概念,分隔符只服务于找到两个点,找到两个点后取出两点间的文本,分隔符被过滤掉。详细可以看文中--分隔符与排序的关系

1. 前提提要、场景

ps aux 可以显示所有的程序进程(不推荐)

  • a: 显示现行终端机下的所有程序,包括其他用户的程序
  • u: 以用户为主的格式来显示程序状况
  • x: 显示所有程序,不以终端机来区分

ps -ef 也可以显示所有的程序进程(推荐)

ps aux 会截断 command 列,而 -ef 不会,所以推荐使用 ps -ef 替代 ps aux

当系统卡顿的时候,我们需要查看系统的资源占用情况,并且排序占用内存、CPU 占用最高的程序靠前。这时候可以使用 sort 命令排序。

查询系统资源占用情况,更快捷的方式是使用 top 命令,在 top 窗口中,P CPU 排序,M 内存排序

2. sort 默认首字母排序

  • 示例文件准备
    sh
    $ cat <<EOF > sort.md
    A 4
    C 2
    B 3
    D 1
    EOF
    
    $ cat <<EOF > sort1.md
    A 14
    C 13
    B 12
    D 11
    EOF
    

命令:sort [File...]

默认按第一列字符 ASCII 排序

sh
$ sort sort.md
A 4
B 3
C 2
D 1 

也可以多个文件内容一块排序

sh
$ sort sort.md sort1.md
A 14
A 4
B 12
B 3
C 13
C 2
D 1
D 11

3. sort -r 降序排序

命令:sort -r [File...]

sh
$ cat <<EOF | sort -r sort.md
A 4
B 3
C 2
D 1 
EOF

D 1
C 2
B 3
A 4

4. sort -k 按列排序

命令:sort -k Start[,End] [File...]

列的起始值是 1, 不是 0

sh
$ cat <<EOF | sort -k 2 sort.md
A 4
B 3
C 2
D 1 
EOF

D 1
C 2
B 3
A 4

5. sort -t 指定分隔符

默认分隔符为空格,但有时候文本的分隔符为其他,这时候就可以用 -t 参数

命令:sort -t [File...]

sh
$ cat <<EOF | sort -t : -k 2
A:14
C:13
B:12
D:11
EOF

D:11
B:12
C:13
A:14

6. 排序细节

6.1 ASCII 码排序

默认根据字符排序,即 ASCII 码排序,如果同一位置具有相同的字符,则继续比对后一位置的 ASCII 码,直到行末。

sh
$ cat <<EOF | sort
130
121
120 
14
13
1
EOF

# 从第一个字符的 ASCII 码开始对比,相同则对比下一位,以此类推
1
120
121
13
130
14

如果想根据数字大小排序,可以使用后续介绍的 -n 参数

6.2 分隔符与排序的关系

sh
$ cat <<EOF | sort -k 1 
15
1 
EOF

# 这个结果大家应该没有疑问
1
15
sh
$ cat <<EOF | sort -k 1 
15 6 
1 6
EOF

# 这个结果就有点出乎意料了
# 不应该 1 小于 15,排前面吗
15 6 
1 6

要解答这个疑问,先看看 之前在介绍 -k ,写的这个简单的命令描述
sort -k Start[,End] [File...]

实际上完整的命令描述为:
sort -k F[.C][OPTS][,F[.C][OPTS]] [File...]

  • F: 字段序号(field number),即第几列,默认 StartF 为第 1 列,EndF 为最后一列
  • c: 在字段中的第几个字符开始对比,默认 StartC 在开始字段的第一个字符,截止 EndC 为行末。
  • [OPTS]: 排序方法 [bdfgiMhnRrV],在 StartEnd 中指定都是等效的。未指定则继承全局

可以理解为 sort -k 只关注两个点之间的内容,毕竟 Fc 的描述的是点的位置(第几列第几个字符)。而分隔符直接过滤掉。

sh
# 现在再回过头来看这道题
$ cat <<EOF | sort -k 1 
15 6 
1 6
EOF

# 这里没有指定前后两个点,所以默认是行头行尾
# 内容为本行全部,再过滤掉分隔符,剩余内容为
156
16

# 根据字符 ASCII 排序,逐字对比排序后,排序如下
156
16

# 补上分隔符
15 6 
1 6

两个点之间的文本,那如果将两个点约束同个列上,例如第 1 列,能否实现我们期待的效果

sh
$ cat <<EOF | sort -k 1,1 
15 6 
1 6
EOF

1 6
15 6

确实可以,这就符合我们的惯性思维了,所以尽量使用 sort -k x,x,指定好 End 在同一列。

继续验证

sh
# 之前的数据是
# 15 6
# 1 6

# 如果把第二行数据的 1 6 改成 1 4
# 去掉分隔符,14 比 15 小,要排前面
# 尝试一下
$ cat <<EOF | sort -k 1 
15 6 
1 4 
EOF

# 和预想一致
1 4 
15 6 

那么不同分隔符对排序有影响吗?
空格的 ASCII 为 32,比数字小。我尝试过比数字大值为 124 的 |,结论是没影响,就不补充 demo 了,有兴趣可以自己试试。

但网上有一些结论是:分隔符作为了文本参与了排序。这个结论我不认同,因为无法解释,为什么换了分隔符排序结果不受影响。

所以我还是保持观点: 分隔符在排序时直接被过滤掉

15 6
1 6
总结一下: 一开始会认为 1 6 要排在 15 6 前面,是主观的认为这里是两个列,对比完第一个列后,再对比第二个列。
但实际上,-k 只会记录前后两个点,由这两个点去获取中间的文本。分隔符可以分隔列,但最终目的,只是服务于找到点的位置。随后取出中间文本后便把分割符过滤了。
使用 sort -k x,x 显性设定 End 在同一列,符合我们的惯性思维。

还有其他小的细节,可以参考 linux sort 命令整理

7. sort -n 按数字大小排序

命令:sort -n [File...]

sh
$ sort -nk 2 sort.md sort1.md
D 1
C 2
B 3
A 4
D 11
B 12
C 13
A 14

8. 字符串排序

前面都是以行为单位排序,也可以配合其他命令,实现以字符为单位的排序

本质是利用 grep -o 将字符串转为行,sort 排序后,tr -d 删除换行符还原为字符串。

sh
# grep -o:--only-matching,仅仅打印匹配到的字符,相当于将 hello 分成每行一个字符
# tr -d '\n':删除所有换行符
$ echo hello | grep -o . | sort | tr -d '\n'
ehllo