Linux文本处理四大利器:cut、sort、uniq、tr 实战指南
前言
在Linux日常运维或数据处理中,文本文件是最常见的数据载体。无论是解析配置文件、统计日志信息,还是整理输出结果,都离不开高效的文本处理工具。cut(列截取)、sort(排序)、uniq(去重)、tr(字符转换)这四个命令,就像文本处理的"四大利器",各自专攻一项核心技能,搭配使用更是能解决绝大多数文本处理难题。本文将用通俗易懂的语言,结合大量实战例子,带你吃透这四个命令的用法。
一、cut:列截取工具
1.1 基本说明
cut命令的核心作用是"截取"------从文本的每一行中,按字节、字符或指定字段提取需要的内容,输出到屏幕或文件。它特别适合处理以单个字符(如冒号、空格、制表符)为分隔符的结构化文本,比如系统配置文件、日志记录等。如果不指定输入文件,cut会读取键盘输入(标准输入)。
1.2 常用选项
| 核心选项 | 功能说明 | 经典示例 | 避坑要点 |
|---|---|---|---|
-b |
按字节截取(仅适合纯英文) | `who | cut -b 3`(取who输出的第3个字节) |
-c |
按字符截取(支持中文) | `cat name.txt | cut -c 2`(取每行第2个字符,中文正常) |
-d |
指定字段分隔符(默认Tab) | 搭配-f使用,如cut -d':' -f1(冒号为分隔符) |
⚠️ 仅支持单个字符 分隔符,多字符(如--)无效 |
-f |
指定要截取的字段编号 (需配-d) |
1. 取第1列:cut -d':' -f1 /etc/passwd(用户名) 2. 取1、3列:cut -d':' -f1,3 /etc/passwd 3. 取1-3列:cut -d':' -f1-3 /etc/passwd |
⚠️ 字段编号从1开始,不是0;无-d时-f无效 |
1.3 使用示例
字段截取(最常用场景)
bash
# 提取/etc/passwd中的用户名(第一列,冒号分隔)
cut -d':' -f1 /etc/passwd
# 输出结果:root、bin、daemon、adm等系统用户
# 提取用户ID(第三列)和用户名(第一列),顺序可调整
cut -d':' -f3,1 /etc/passwd
# 输出结果:0:root、1:bin、2:daemon等
# 提取第一到第三列(用户名:密码:用户ID)
cut -d':' -f1-3 /etc/passwd
# 输出结果:root:x:0、bin:x:1等
按字符/字节截取
bash
# 截取name.txt文件中每一行的第2个字符(中文也能正确识别)
cat name.txt | cut -c 2
# 若name.txt内容是"蔡文海、simon、谭文俊",输出:文、i、文
# 截取who命令输出的第3个字节(适合纯英文)
who | cut -b 3
# who输出"root pts/4 2025-08-31 11:44(192.168.10.2)",输出:o
二、sort:排序工具(默认按行首字符升序)
2.1 基本说明
sort命令用于对文本内容按"行"排序,默认规则是按行首字符的ASCII码升序排列(即字典序,比如数字10会排在2前面)。它支持自定义分隔符、排序字段和排序规则(升序/降序、数字/字符排序),还能直接去重或输出到指定文件。
2.2 常用选项
| 核心选项 | 功能说明 | 经典示例 | 避坑要点 |
|---|---|---|---|
-n |
按数值大小排序(默认是字典序) | sort -n num.txt(对数字列表排序,如10不会排在2前) |
⚠️ 不加-n时,10会比2小(字典序:1<2),必加! |
-r |
按降序排序(默认升序) | sort -nr num.txt(数字降序);sort -nr -t':' -k3 /etc/passwd(按UID降序) |
✅ 通常与-n搭配,单独用-r仅反转字典序 |
-t |
指定字段分隔符 (同cut的-d) |
搭配-k使用,如-t':'(冒号分隔) |
⚠️ 分隔符仅支持单个字符,多字符需先处理(如用tr压缩) |
-k |
指定排序字段编号 (需配-t) |
sort -n -t':' -k3 passwd.txt(按第3列数值升序) |
⚠️ 字段编号从1开始,如-k3指第3列,不是第2列 |
-u |
排序同时去重 (等价于sort + uniq) |
sort -u fruit.txt(去重并排序) |
⚠️ 行尾有空格时,相同内容会被视为不同行,需先清理空格 |
-o |
将排序结果输出到文件(默认输屏幕) | sort -nr -t':' -k3 passwd.txt -o passwd_bak.txt |
⚠️ 不能用>直接重定向(如sort ... > file),会清空原文件 |
2.3 使用示例
基础排序
bash
# 对passwd.txt按第一列(用户名)字典序升序排序
sort passwd.txt
# 按第三列(用户ID)数值升序排序(冒号分隔)
sort -n -t':' -k3 passwd.txt
# 输出结果按UID从0(root)、1(bin)、2(daemon)依次排列
# 按用户ID数值降序排序,并保存到passwd_bak.txt
sort -nr -t':' -k3 passwd.txt -o passwd_bak.txt
去重排序
bash
# 对fruit.txt排序并去重(重复行只保留一行)
sort -u fruit.txt
# 等价于:sort fruit.txt | uniq
# 对数字列表按数值降序排序(避免字典序坑)
echo -e "10\n2\n35\n8" | sort -nr
# 输出结果:35、10、8、2(若不加-n,会输出35、8、2、10)
三、uniq:去除重复行工具
3.1 基本说明
uniq命令的核心是"去重",但有个关键限制:只能去除连续的重复行。如果重复行不相邻,它无法识别。因此,uniq几乎总是和sort搭配使用------先通过sort将重复行排到一起,再用uniq去重或统计,实现全局去重效果。
3.2 常用选项
| 核心选项 | 功能说明 | 经典示例 | 避坑要点 |
|---|---|---|---|
| 无选项 | 去除连续的重复行(非连续不处理) | uniq fruit.txt(仅合并相邻重复行,如不连续的banana保留) |
⚠️ 最大坑 :无法处理非连续重复行,必须先sort! |
-c |
统计每行的重复次数(含唯一行) | `sort fruit.txt | uniq -c`(输出如"2 apple""1 pear") |
-d |
只显示至少重复1次的行(即重复行) | `sort fruit.txt | uniq -d`(仅输出apple、banana等重复项) |
-u |
只显示仅出现1次的行(唯一行) | `sort fruit.txt | uniq -u`(仅输出orange、pear等非重复项) |
3.3 使用示例
先创建一个测试文件fruit.txt,内容如下:
apple
apple
peache
pear
banana
cherry
cherry
banana
orange
基础去重与统计
bash
# 直接去重(仅去除连续重复行,不连续的banana无法去重)
uniq fruit.txt
# 输出结果:apple、peache、pear、banana、cherry、banana、orange
# 全局去重(先排序再去重)
sort fruit.txt | uniq
# 输出结果:apple、banana、cherry、orange、peache、pear
# 统计每行出现次数(全局)
sort fruit.txt | uniq -c
# 输出结果:2 apple、2 banana、2 cherry、1 orange、1 peache、1 pear
# 只显示重复行(出现次数≥2)
sort fruit.txt | uniq -d
# 输出结果:apple、banana、cherry
# 只显示唯一行(出现次数=1)
sort fruit.txt | uniq -u
# 输出结果:orange、peache、pear
3.4 实际应用示例
bash
# 查看当前登录的用户(去重,避免同一用户多次登录重复显示)
who | awk '{print $1}' | uniq
# 输出结果:root(若root通过多个终端登录,只显示一次)
# 查看所有登录过系统的用户(去重+过滤空行和无用信息)
last | awk '{print $1}' | sort | uniq | grep -v "^$" | grep -v "wtmp"
# 输出结果:root、reboot等实际登录过的用户/操作
四、tr:字符替换与删除工具
4.1 基本说明
tr命令是"字符处理小能手",专门用于单个字符的替换、删除或重复压缩。它不支持字段级操作,只处理单个字符或字符集,从标准输入读取数据,输出到标准输出。语法格式简单:tr [选项] 字符集1 [字符集2]。
4.2 常用选项
| 核心选项 | 功能说明 | 经典示例 | 避坑要点 |
|---|---|---|---|
| 无选项 | 字符一对一替换(SET1→SET2) | 1. 小写转大写:tr 'a-z' 'A-Z' < fruit.txt 2. a→s、p→a:tr 'ap' 'sa' < fruit.txt |
⚠️ 替换是"按位置对应",SET1和SET2长度不同时,短的用最后字符补 |
-d |
删除SET1中的所有字符 | 1. 删除a:tr -d 'a' < fruit.txt 2. 删除换行符(合并行):tr -d '\n' < fruit.txt |
⚠️ 删多字符时,SET1是"字符集"(如tr -d 'apple'删a/p/l/e),不是字符串 |
-s |
压缩连续重复的字符(保留1个) | 1. 压缩多空格为1个:tr -s " " < log.txt 2. 压缩空行:tr -s '\n' < messy.txt |
⚠️ 只压缩"连续重复"的字符,非连续重复不处理(如"a b a"不压缩) |
4.3 使用示例
字符替换
bash
# 小写字母转大写(字符集对应替换)
cat fruit.txt | tr 'a-z' 'A-Z'
# 输出结果:APPLE、APPLE、PEACHE、PEAR等
# 一对一替换(a→s、p→a、l→r、e→t)
cat fruit.txt | tr 'aple' 'sart'
# 输出结果:sartt、sartt、peacht、pear等
# 替换特定字符为空格(将a替换为空格)
cat fruit.txt | tr 'a' ' '
# 输出结果: pple、 pple、 peche、 pe r等
# 多字符替换为同一个(a和p都替换为/)
cat fruit.txt | tr 'ap' '/'
# 输出结果:///le、///le、/e/che等
字符删除与压缩
bash
# 删除所有a字符
cat fruit.txt | tr -d 'a'
# 输出结果:pple、pple、peche、pe r等
# 删除换行符(将所有行合并为一行)
cat fruit.txt | tr -d '\n'
# 输出结果:appleapplepeachepearbananacherrycherrybananaorange
# 压缩连续重复的p字符(多个p缩为一个)
cat fruit.txt | tr -s 'p'
# 输出结果:aple、aple、peache、pear等
# 压缩空行(多个连续换行符缩为一个)
cat messy.txt | tr -s '\n'
# 适合处理有大量空行的杂乱文本
五、实战应用示例
5.1 统计当前连接的主机数
需求:统计服务器当前有多少个不同的TCP连接主机(即不同的客户端IP)。
bash
# 方法1:用ss命令(推荐,效率更高)
ss -nt | tr -s " " | cut -d " " -f5 | cut -d ":" -f1 | sort | uniq -c | grep -v "Address"
# 方法2:用netstat命令(兼容旧系统)
netstat -nt | grep -vE '^Proto|^Active' | tr -s " " | cut -d " " -f5 | cut -d ":" -f1 | sort | uniq -c
命令拆解:
- ss -nt/netstat -nt:获取所有TCP连接(-n不解析端口名,-t只显示TCP)。
- tr -s " ":将输出中的多个连续空格压缩为一个,方便后续截取。
- cut -d " " -f5:以空格为分隔符,截取第5列(客户端IP:端口)。
- cut -d ":" -f1:以冒号为分隔符,截取IP部分(去掉端口)。
- sort | uniq -c:排序后统计每个IP的连接次数。
- grep -v:过滤掉表头或无用信息。
5.2 统计当前主机的连接状态
需求:统计服务器TCP连接的状态分布(如ESTABLISHED、LISTEN的数量)。
bash
# 方法1:用ss命令
ss -nta | grep -v '^State' | cut -d " " -f1 | sort | uniq -c
# 方法2:用netstat命令
netstat -ant | grep -vE '^Proto|^Active' | tr -s " " | cut -d " " -f6 | sort | uniq -c
输出示例:
2 ESTAB # 2个已建立的连接
4 LISTEN # 4个监听状态的端口
总结
cut、sort、uniq、tr这四个命令,各自聚焦文本处理的一个核心环节:cut负责"截取"需要的字段,sort负责"排序"规整顺序,uniq负责"去重"和统计,tr负责"转换"字符形态。它们单独使用能解决单一问题,组合使用则能应对复杂的文本处理场景------比如日志分析、数据统计、配置解析等。
学习这些命令的关键在于"多练":结合实际需求,尝试修改命令选项、替换输入文件,观察输出结果的变化。熟练掌握后,你会发现处理文本文件不再是繁琐的手工操作,而是高效精准的命令组合。