Linux文本排序统计命令:sort、uniq、wc、cut、tr实战

处理日志、导出数据、统计访问量时,sort、uniq、wc、cut、tr 这五条命令是管道里最常出现的组合。它们单个都不复杂,拼在一起却能干掉一大半"把一大坨文本整理成人能看的东西"的活。这一篇把语法、参数和实战用法过一遍。

一、sort:排序

语法格式

复制代码
sort [选项] [文件]

不带文件时从标准输入读。默认按字典序排,这也是新手最容易踩的坑:10 会排在 2 前面。

常用参数

参数 说明
-n 按数值大小排序,不是字典序
-r 逆序(从大到小 / Z 到 A)
-k 字段号 按第几个字段排序,字段从 1 开始
-t 分隔符 指定字段分隔符,默认是空白
-u 排序后去重(等价于 sort 后接 uniq)
-f 忽略大小写
-h 按人类可读数字排序(1K、2M、3G)
-M 按月份缩写排序(JAN、FEB...)

示例与预期输出

先准备一份测试数据 visits.log,每行是"IP 访问次数":

复制代码
192.168.1.10 320
10.0.0.5 15
192.168.1.10 320
172.16.0.8 89
10.0.0.5 15
192.168.1.200 1024

示例 1:按第二列数值倒序

复制代码
sort -k2 -nr visits.log

预期输出:

复制代码
192.168.1.200 1024
192.168.1.10 320
172.16.0.8 89
10.0.0.5 15
192.168.1.10 320
10.0.0.5 15

-k2 指定按第二列,-n 告诉 sort 这列是数字,-r 倒过来。注意重复行还在,去重交给后面的 uniq。

示例 2:按冒号分隔的字段排序

/etc/passwd 用冒号分 7 段,想按 UID(第三段)排:

复制代码
sort -t: -k3 -n /etc/passwd | head -5

预期输出:

复制代码
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync

-t: 把分隔符换成冒号,-k3 才不会按整行乱排。

二、uniq:去重

语法格式

复制代码
uniq [选项] [输入文件 [输出文件]]

常用参数

参数 说明
-c 在每行前打印出现次数
-d 只显示重复过的行
-u 只显示从未重复的行
-i 忽略大小写

⚠️ 关键前提:先排序再 uniq

uniq 只合并相邻 的重复行。原始数据里 192.168.1.10 出现两次但中间隔着别的行,直接 uniq visits.log 是去不掉的。所以标准套路是:

复制代码
sort visits.log | uniq -c

预期输出:

复制代码
      2 10.0.0.5 15
      1 172.16.0.8 89
      2 192.168.1.10 320
      1 192.168.1.200 1024

-c 把每行出现次数放在最前面。想找"谁访问次数最多",再接一层排序:

复制代码
sort visits.log | uniq -c | sort -k1 -nr

预期输出:

复制代码
      2 192.168.1.10 320
      2 10.0.0.5 15
      1 192.168.1.200 1024
      1 172.16.0.8 89

这就是日志统计里最经典的一条管道:排序、去重计数、再按次数倒序。

三、wc:统计行数、单词数、字节数

语法格式

复制代码
wc [选项] [文件]

常用参数

参数 说明
-l 只统计行数(最常用)
-w 统计单词数
-c 统计字节数
-m 统计字符数(中文场景下比 -c 准)

示例与预期输出

复制代码
wc -l /etc/passwd

预期输出:

复制代码
35 /etc/passwd

不带参数时三个数一起出:

复制代码
wc /etc/passwd

预期输出(字段依次是行、单词、字节):

复制代码
      35     110    1680 /etc/passwd

配合管道用得最多:ps aux | wc -l 数进程,find . -name "*.py" | wc -l 数文件个数。注意 find ... | wc -l 比 ls | wc -l 靠谱,后者遇到文件名带换行符会数错。

四、cut:按列切文本

语法格式

复制代码
cut [选项] 文件

常用参数

参数 说明
-d 分隔符 指定字段分隔符
-f 列号 取第几列,-f1,3 取 1 和 3,-f2- 取第 2 列到末尾
-c 字符位置 按字符位置切,-c1-10 取前 10 个字符

示例与预期输出

把 /etc/passwd 的用户名(第 1 列)和登录 Shell(第 7 列)抽出来:

复制代码
cut -d: -f1,7 /etc/passwd | head -5

预期输出:

复制代码
root:/bin/bash
daemon:/usr/sbin/nologin
bin:/usr/sbin/nologin
sys:/usr/sbin/nologin
sync:/bin/sync

-d: 和 -f1,7 是固定搭配。想只看哪些账号能真正登录:

复制代码
grep -v nologin /etc/passwd | cut -d: -f1,7

五、tr:字符替换与删除

tr 和前面几个不一样,它不接文件名,只读标准输入,主要靠管道喂数据。

语法格式

复制代码
echo "文本" | tr [选项] 集合1 [集合2]

常用参数

参数 说明
-d 集合 删除集合中出现的字符
-s 集合 把连续重复的字符压缩成一个
无参数 把集合 1 里的每个字符替换成集合 2 对应位置的字符

示例与预期输出

小写转大写:

复制代码
echo "Hello World" | tr 'a-z' 'A-Z'

预期输出:

复制代码
HELLO WORLD

去掉文本里的换行和多余空格:

复制代码
echo "a   b  c" | tr -s ' '

预期输出:

复制代码
a b c

把 Windows 换行(\r\n)里的 \r 删掉,变相实现 dos2unix:

复制代码
tr -d '\r' < windows.txt > unix.txt

\r 在 tr 里写成 '\r'。这条命令处理从 Windows 拷过来的脚本文件特别好使。

六、知识扩展:sort -u 和 uniq 的取舍,以及字段排序的边界

sort -u 和 sort | uniq 都能去重,区别在哪?

sort -u 只保留每组重复里第一行 ;uniq 不加 -c 时行为一样。但当你需要"既去重又要看到每组出现几次",必须 sort | uniq -c,sort -u 给不出计数。性能上两者差别可以忽略,写法按目的选。

字段排序还有个容易翻车的点:-k2 不是"从第 2 个字符开始",而是"从第 2 个字段的开头,一直排到行尾"。想精确到字段内部的某个字符位置,得写 -k2.1,2.3 这种"起始.结束"格式。比如想按 IP 第三段排,直接 -k3 -t. 会按字典序把 10 排在 8 前面,这时候要加 -n 才对。

最后一个组合技巧:统计 Nginx 日志里访问量最高的 5 个 IP。

复制代码
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -k1 -nr | head -5

整条链路读下来就是:awk 抽第一列 IP → sort 排序让相同 IP 相邻 → uniq -c 计数 → sort -k1 -nr 按次数倒序 → head 取前 5。awk 那一列后面会专门讲,这里先把管道串起来感受一下。

相关推荐
clz13145212 小时前
双重检查锁 DCL 终极优化:懒加载 + 线程安全 + 高性能
java
CRMEB2 小时前
前后端技术栈全面换代!CRMEB 多商户(Java)v3.0更新预告
java·开发语言
开发者联盟league2 小时前
c++11 使用chrono库转换时间点和字符串,计算时间点间隔
java·c++·算法
我最爱吃鱼香茄子2 小时前
【毕业设计优选】人力资源管理系统|Java|SpringBoot|Vue|前后端分离|带详细文档+部署教学视频
java·vue·毕业设计·springboot
JQLvopkk2 小时前
HslCommunication,一个工具测遍所有 PLC
开发语言·人工智能·c#·交互
阿狗童鞋2 小时前
Python爬虫进阶实战指南
开发语言·爬虫·python
下页、再停留2 小时前
【C#桌面客户端系列学习-7】数据查询展示
开发语言·c#·visual studio
步行cgn2 小时前
Spring 只读事务面试详解
java·spring·面试
APIshop2 小时前
淘宝详情接口全解析:从官方开放平台到第三方数据服务
java·python·api