文本排序与统计:sort、uniq、wc
sort:文本排序
sort 对文本行进行排序,支持多种排序规则和字段选择。
# 基本排序(按字母顺序)
sort file.txt
# 反向排序(-r reverse)
sort -r file.txt
# 数字排序(-n numeric,避免 10 排在 2 前面)
sort -n numbers.txt
# 按第 2 列排序(-k key)
sort -k2 file.txt
# 按第 2 列数字排序
sort -k2 -n file.txt
# 指定分隔符后按列排序(-t separator)
sort -t: -k3 -n /etc/passwd # 按 UID 排序
# 去重排序(-u unique)
sort -u file.txt
# 忽略前导空白(-b ignore-leading-blanks)
sort -b file.txt
# 忽略大小写(-f ignore-case)
sort -f file.txt
# 检查是否已排序(-c check)
sort -c file.txt
# 如果未排序,输出错误信息
# 合并多个已排序文件(-m merge)
sort -m file1.txt file2.txt
sort 关键选项
| 选项 | 作用 | 示例 |
|---|---|---|
-n | 数字排序 | sort -n(10 在 9 后面) |
-r | 反向排序 | sort -rn(从大到小) |
-k | 按第 n 列排序 | sort -k3 |
-t | 指定分隔符 | sort -t: |
-u | 去重 | sort -u |
-f | 忽略大小写 | sort -f |
-b | 忽略前导空白 | sort -b |
uniq:去重与统计
uniq 去除相邻的重复行。注意:它只能去除相邻重复,所以通常先 sort 再 uniq。
# 基本去重(只去除相邻重复)
uniq file.txt
# 排序后去重(最常用组合)
sort file.txt | uniq
# 统计每行出现次数(-c count)
sort file.txt | uniq -c
# 只显示重复的行(-d repeated)
sort file.txt | uniq -d
# 只显示不重复的行(-u unique)
sort file.txt | uniq -u
# 忽略前 N 个字符后比较(-s skip-chars)
uniq -s 5 file.txt
# 只比较前 N 个字符(-w check-chars)
uniq -w 3 file.txt
# 忽略大小写(-i ignore-case)
uniq -i file.txt
uniq 输出解读
$ sort file.txt | uniq -c
3 apple
1 banana
2 cherry
表示:apple 出现 3 次,banana 出现 1 次,cherry 出现 2 次。
wc:字数统计
wc(Word Count)统计文件的行数、单词数和字节数。
# 统计所有信息
wc file.txt
# 输出:行数 单词数 字节数 文件名
# 只统计行数(-l lines)
wc -l file.txt
# 只统计单词数(-w words)
wc -w file.txt
# 只统计字节数(-c bytes)
wc -c file.txt
# 统计字符数(-m chars,多字节字符更准确)
wc -m file.txt
# 从管道读取
ls /bin | wc -l # /bin 下有多少个命令
cat file.txt | wc -l # 文件有多少行
wc 输出解读
$ wc file.txt
10 20 150 file.txt
# 10 行
# 20 个单词(以空白分隔)
# 150 字节
黄金组合:日志分析
场景 1:统计访问最多的 IP
# Nginx 访问日志,第 1 列是 IP
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -n 10
# 分解:
# awk '{print $1}' 提取 IP 列
# sort 排序(让相同 IP 相邻)
# uniq -c 统计每个 IP 出现次数
# sort -rn 按次数从大到小排序
# head -n 10 取前 10 名
场景 2:统计状态码分布
# 第 9 列是 HTTP 状态码
awk '{print $9}' access.log | sort | uniq -c | sort -rn
# 输出示例:
# 5000 200
# 1200 404
# 300 500
# 100 301
场景 3:统计目录下文件数量
# 统计当前目录下有多少文件
ls | wc -l
# 统计 /bin 下有多少命令
ls /bin | wc -l
# 统计代码行数
find . -name "*.py" | xargs wc -l
场景 4:查找大文件
# 找出当前目录下最大的 10 个文件
ls -lS | head -n 11 | tail -n +2
# 或更精确的方式
find . -type f -exec ls -l {} + | sort -k5 -rn | head -n 10
本篇小结
sort:文本排序,-n数字排序,-r反向,-k按列,-t指定分隔符uniq:去除相邻重复,-c统计次数,-d只显示重复,-u只显示唯一wc:统计行数(-l)、单词数(-w)、字节数(-c)- 黄金组合:
awk '{print $N}' | sort | uniq -c | sort -rn | head - 注意:
uniq只能去相邻重复,通常需要先sort
动手实践
sort 排序练习:
cat > numbers.txt 10 2 100 25 1 # Ctrl+D sort numbers.txt # 字母排序 sort -n numbers.txt # 数字排序 sort -rn numbers.txt # 数字反向uniq 去重练习:
cat > fruits.txt apple banana apple cherry banana apple # Ctrl+D uniq fruits.txt # 不去重(不相邻) sort fruits.txt | uniq # 去重 sort fruits.txt | uniq -c # 统计 sort fruits.txt | uniq -d # 只显示重复的wc 统计练习:
wc fruits.txt wc -l fruits.txt wc -w fruits.txt ls /bin | wc -l黄金组合实战:
# 如果有 Nginx 日志 awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn # 统计 /etc/passwd 中每种 Shell 的用户数 awk -F: '{print $7}' /etc/passwd | sort | uniq -c | sort -rn综合练习:
# 找出当前目录下最大的 5 个子目录 du -sh * | sort -rh | head -n 5思考:为什么
uniq只能去除相邻的重复行?如果数据是apple banana apple,uniq能去重吗?如何解决这个问题?