Shell脚本学习指南-第四章-文本处理工具
第4章 文本处理工具
4.1 sort 排序文本
sort:按行对文本排序;把每行当作记录,空白/指定字符切分成字段。
⚠重点坑:排序结果受locale(语言区域)影响;脚本稳定排序建议:LC_ALL=C sort使用原始ASCII字节排序。
常用选项汇总
| 选项 | 说明 |
|---|---|
-b |
忽略行开头空白 |
-C |
仅检查是否有序,不输出,用退出码判断结果 |
-d |
字典序,只看字母数字空格,忽略标点 |
-f |
忽略大小写 |
-g |
GNU扩展,浮点数排序,不可移植 |
-i |
忽略不可打印字符 |
-k |
指定排序键(字段、字符区间) |
-m |
输入已经有序,只做合并,不重新排序 |
-n |
按整数数值排序,不是ASCII字符比较 |
-o file |
输出写入文件,可以直接覆盖输入文件(安全,内部用临时文件) |
-r |
反转,降序从大到小 |
-t 字符 |
设置字段分隔符,只能单个字符;默认空白分割 |
-u |
去重:只对比排序键,键相同就丢弃,不对比整行全部内容 |
重要:
sort a.txt > a.txt错误!会直接清空源文件;覆盖文件请用sort -o a.txt a.txt。
-k 排序键用法(高频)
-kN:从第N字段开始,一直到行末尾结束(不是到本字段末尾)-kN,M:从第N字段开始,到第M字段结束(推荐写,边界明确)- 修饰符直接跟在数字后面:
n数字、r逆序、f忽略大小写 - 多个
‑k代表多条件排序:第一个条件相同才比对下一个条件。
示例文件 /etc/passwd,冒号:分隔字段
多行记录块排序(记录之间空行分隔)
场景:一条数据占多行,记录之间用空行隔开,不能直接‑k。
思路:
- 把块内换行替换成一个特殊标记字符,整条记录变成单行
- sort排序
- 再把标记还原回换行
RS="":awk输入记录分隔符,空行代表记录分割ORS="\n\n":输出记录之间输出空行gsub():全局字符串替换
sort稳定性
稳定排序:排序键相等,保留原始输入的先后顺序。
POSIX不要求sort稳定;GNU sort加参数
--stable开启稳定排序。
sort小结
- 脚本固定
LC_ALL=C sort,消除不同系统locale带来排序结果差异。 -n整数;‑g浮点数GNU独有,跨平台不要用。- 覆盖文件使用
-o,不要重定向>源文件。 -u只对比排序键,不是整行去重。
4.2 uniq 删除重复行
⚠关键:uniq只消除相邻连续的重复行!分散的重复识别不到。
标准用法:sort | uniq,先排序让相同行挨在一起。
| 选项 | 作用 |
|---|---|
-c |
统计重复次数,输出「计数 内容」 |
-d |
只输出出现过重复的行 |
-u |
只输出只出现一次、没有重复的行 |
示例
sort -uVSsort | uniq
sort -u:对比排序键;sort | uniq:对比整行全部内容。想要完整行去重,优先管道uniq。
4.3 fmt 段落重排格式化
把长文本折行,控制每行宽度;不属于POSIX标准,老旧UNIX不一定有。
| 选项 | 说明 |
|---|---|
‑s |
只拆分超长行;短行不会互相合并 |
‑w N |
设置输出行宽度,默认约75字符(GNU) |
示例
|
|
可移植脚本尽量避免fmt,各个系统参数行为差异很大。
4.4 wc 统计:行数、单词、字节/字符
默认输出顺序:行数 单词数 字节数
| 选项 | 作用 |
|---|---|
‑l |
统计行数 |
‑w |
统计单词(空白分割) |
‑c |
统计字节数 |
‑m |
统计字符数,适合UTF‑8多字节中文 |
统计行为受
LC_CTYPE语言环境影响。
4.5 打印相关工具
两套历史打印体系:Berkeley 与 System V
| 操作 | Berkeley | System V |
|---|---|---|
| 打印文件 | lpr |
lp |
| 取消任务 | lprm |
cancel |
| 查看队列 | lpq |
lpstat -o |
环境变量:
- Berkeley:
PRINTER指定打印机 - System V:
LPDEST指定打印机
pr:打印预处理分页工具
pr不直接打印;做分页、加页眉、多栏格式化,输出交给lp/lpr。
常用选项
| 选项 | 说明 |
|---|---|
‑c n / -n |
输出n列多栏 |
‑f |
分页符,分页 |
‑h "文本" |
自定义页眉,替换默认文件名时间 |
‑l n |
每页行数 |
‑o n |
整体向右偏移n个空格 |
‑t |
关闭页眉页脚 |
‑w N |
设置行宽度 |
示例:5栏输出,关闭页眉
|
|
4.6 head / tail 截取开头结尾
head:取文件前面若干行
tail:取文件末尾若干行
4.7 其他小工具速览
| 命令 | 用途 |
|---|---|
od |
输出原始八进制/十六进制字节,查看二进制文件内部 |
file |
检测文件类型 |
strings |
从二进制程序提取可打印文本字符串 |
dd |
块拷贝;字符转换优先用iconv |
示例
|
|
本章速查表格
| 命令 | 作用 | 示例 |
|---|---|---|
sort -t: -k1,1n |
按指定字段排序 | sort -t: -k3nr,3 /etc/passwd 按UID降序 |
LC_ALL=C sort |
固定ASCII字节排序,脚本稳定输出 | LC_ALL=C sort data.txt |
sort -u |
按排序键去重 | sort -k2,2 -u file.txt |
sort -o out.txt |
安全输出覆盖文件 | sort -o file.txt file.txt |
sort uniq -c |
排序并统计每行出现次数 | tr -cs A-Za-z' ‘\n’ < test.txt | sort | uniq -c |
uniq -d |
只输出重复行 | sort test.txt | uniq -d |
fmt -w 40 |
文本折行,设置行宽 | fmt -w 40 note.txt |
wc -lwc |
统计行、单词、字节 | wc /etc/passwd |
pr -c4 -t |
多栏格式化,关闭页眉 | cat words.txt | pr -c4 -t |
head -n 10 |
取前10行 | head -n 10 /etc/passwd |
tail -n 20 |
取末尾20行 | tail -n 20 /var/log/syslog |
tail -f |
跟踪日志增长(交互式) | tail -f /var/log/messages |
本章小结
sort是本章重点;locale环境变量是高频坑,脚本建议固定LC_ALL=C sort。uniq只处理相邻重复,必须搭配sort;区分sort‑u(按键去重)和sort|uniq(整行去重)。fmt非POSIX,可移植脚本尽量少用。wc统计行、词、字节字符。pr用于打印前分页、多栏排版;head、tail截取首尾。- 工具设计哲学:输入输出为标准流,管道串联完成复杂文本处理。
文章作者 会写代码的小郎中
上次更新 2011-07-17
许可协议 CC BY-NC-ND 4.0