Linux处理文本
Linux 文本处理工具
Linux 系统提供了大量强大且灵活的文本处理工具,以下是常用的分类整理及典型用法示例:
一、查看与浏览工具
cat
- 查看文件内容或合并文件。
- 示例:
cat file.txt
- 替代工具:
bat
(支持语法高亮、分页)。
less
/more
- 分页查看大文件(支持上下翻页)。
- 示例:
less large.log
。
head
/tail
- 查看文件头部或尾部内容。
- 示例:
tail -n 100 error.log
(显示最后100行)。
二、搜索与过滤工具
grep
- 按正则表达式搜索文本。
- 示例:
grep "error" log.txt
(查找含 “error” 的行)。 - 替代工具:
ripgrep (rg)
(更快,支持.gitignore
)。
ack
/ag
- 针对代码的增强搜索工具(自动忽略版本控制文件)。
- 示例:
ag "function_name" src/
。
三、处理与转换工具
sed
- 流编辑器,用于替换、删除、插入文本。
- 示例:
sed 's/foo/bar/g' file.txt
(全局替换 foo 为 bar)。
awk
- 强大的文本分析工具,支持字段处理。
- 示例:
awk '{print $1}' data.txt
(输出第一列)。
cut
- 按列切割文本。
- 示例:
cut -d',' -f1-3 data.csv
(提取 CSV 文件的前三列)。
tr
- 字符替换或删除。
- 示例:
tr 'a-z' 'A-Z' < file.txt
(转大写)。
sort
- 排序文本行。
- 示例:
sort -n data.txt
(按数值排序)。
uniq
- 去重相邻重复行(常与
sort
结合)。 - 示例:
sort file.txt | uniq -c
(统计重复次数)。
四、统计与分析工具
wc
- 统计行数、单词数、字节数。
- 示例:
wc -l access.log
(统计行数)。
paste
- 合并文件列。
- 示例:
paste file1.txt file2.txt
(按列合并)。
join
- 按共同字段连接两个文件(类似 SQL JOIN)。
- 示例:
join file1.txt file2.txt
。
五、替换与编辑工具
perl
- 支持复杂正则替换(常用于一行命令)。
- 示例:
perl -pi -e 's/old/new/g' *.txt
(批量替换文件内容)。
vim
/ex
- 交互式文本编辑(
ex
适合脚本化操作)。 - 示例:
ex -sc '%s/foo/bar/g|x' file.txt
(非交互式替换)。
六、结构化文本处理
jq
- 解析和操作 JSON 数据。
- 示例:
curl API | jq '.data[].name'
。
yq
- 处理 YAML/XML/JSON 文件(类似
jq
的功能)。 - 示例:
yq '.key.subkey' config.yaml
。
xmlstarlet
- XML 解析和转换工具。
- 示例:
xmlstarlet sel -t -v "//title" file.xml
。
七、多文件与差异处理
diff
- 比较文件差异。
- 示例:
diff file1.txt file2.txt
。
patch
- 应用差异文件。
- 示例:
patch original.txt < diff.patch
。
comm
- 比较两个有序文件的异同。
- 示例:
comm file1.txt file2.txt
。
八、其他实用工具
column
- 格式化文本为表格。
- 示例:
ps aux | column -t
(对齐进程信息)。
fmt
- 文本段落格式化。
- 示例:
fmt -w 80 long_text.txt
(设置每行80字符)。
split
- 分割大文件。
- 示例:
split -l 1000 bigfile.txt part_
(按每1000行分割)。
组合使用示例
- 统计日志中错误出现的次数并排序:
grep "ERROR" app.log | sort | uniq -c | sort -nr ```- 提取 CSV 文件的第2列并去重: ```bash cut -d',' -f2 data.csv | sort | uniq
掌握这些工具后,可通过管道(`|`)组合它们,高效处理文本任务。学习曲线由浅入深,建议从 `grep`、`sed`、`awk` 开始逐步深入。
## Linux文本处理三剑客
在 Linux 文本处理领域,**`grep`、`sed`、`awk`** 被并称为“文本处理三剑客”。它们分别专注于 **搜索过滤**、**流式编辑** 和 **结构化分析**,是 Shell 脚本和日常文本处理的基石工具。以下是它们的详细介绍和典型用法示例:
---
### **1. `grep`:文本搜索之王**
- **功能**:基于正则表达式(或简单字符串)快速搜索文本,输出匹配的行。
- **核心用途**:过滤日志、提取关键信息、快速定位内容。
- **常用参数**:
- `-i`:忽略大小写
- `-v`:反向匹配(输出不匹配的行)
- `-r`:递归搜索目录
- `-n`:显示行号
- `-C NUM`:显示匹配行前后 NUM 行的上下文
**示例**:
```bash
# 在文件中搜索 "error"(区分大小写)
grep "error" server.log
# 忽略大小写搜索 "warning"grep -i "warning" app.log
# 递归搜索目录中所有文件,并显示行号
grep -rn "login_failed" /var/log/
# 查找所有非空行
grep -v "^$" config.txt
# 提取包含 IP 地址的行(简单正则)
grep -Eo "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" access.log
2. sed
:流式文本编辑器
- 功能:通过脚本对文本进行流式编辑(替换、删除、插入等),支持正则表达式。
- 核心用途:批量替换、删除冗余内容、格式化文本。
- 常用参数:
-i
:直接修改文件(原地编辑)-e
:指定编辑命令-n
:静默模式(仅输出处理后的行)
示例:
# 全局替换 "apple" 为 "orange"(仅输出到屏幕)
sed 's/apple/orange/g' fruits.txt
# 直接修改文件(危险操作前建议备份!)
sed -i 's/foo/bar/g' *.txt
# 删除所有空行
sed '/^$/d' input.txt
# 替换第 5 行的内容
sed '5c This is new line' data.txt
# 在每行行首添加时间戳(使用扩展正则)
date=$(date +"%Y-%m-%d")
sed "s/^/$date /" log.txt
3. awk
:结构化文本处理大师
- 功能:基于字段和模式处理结构化文本(如 CSV、日志等),支持编程逻辑。
- 核心用途:统计报表、字段提取、复杂数据转换。
- 核心语法:
awk 'pattern {action}' file
- 默认按空格/制表符分割字段(
$1
为第一列,$0
为整行) - 内置变量:
NR
(行号)、NF
(字段数)、FS
(输入分隔符)、OFS
(输出分隔符)
示例:
# 提取 CSV 文件的第 2 列(假设分隔符为逗号)
awk -F',' '{print $2}' data.csv
# 统计文件行数
awk 'END {print NR}' large.log
# 计算第 3 列的总和
awk '{sum += $3} END {print sum}' sales.txt
# 过滤第 5 列大于 100 的行
awk '$5 > 100 {print $0}' metrics.txt
# 自定义输出格式(合并字段)
awk -F':' '{print "User:", $1, "Home:", $6}' /etc/passwd
# 复杂逻辑:统计 HTTP 状态码出现次数
awk '{status[$9]++} END {for (s in status) print s, status[s]}' access.log
三剑客组合使用示例
案例 1:分析 Nginx 日志
# 提取访问量最高的前 5 个 IPawk '{print $1}' access.log | sort | uniq -c | sort -nr | head -n 5
# 统计 404 错误的数量
grep " 404 " access.log | awk '{print $9}' | uniq -c
案例 2:批量重命名文件
# 将所有 .txt 文件中的 "old_" 前缀删除
ls *.txt | sed 's/old_//' | xargs -I {} mv old_{} {}
案例 3:生成简易报告
# 统计不同进程的内存占用总和
ps aux | awk '{mem[$11] += $6} END {for (p in mem) print p, mem[p]/1024 "MB"}'
总结
grep
:快速定位关键内容,适合初步过滤。sed
:轻量级文本编辑,适合单行处理。awk
:处理结构化数据,支持复杂逻辑和计算。
学习建议:
- 先掌握
grep
的正则表达式和常用参数。 - 熟悉
sed
的替换 (s///
) 和删除 (d
) 命令。 - 学习
awk
的字段操作和统计技巧。 - 通过管道 (
|
) 组合三者,解决实际问题。
它们的组合能覆盖 90% 的日常文本处理需求,是 Linux 工程师的必备技能!
管道
管道(Pipe)的基本概念
在 Linux 中,管道(符号为 |
)是一种进程间通信机制,允许将一个命令的标准输出(stdout)直接传递给另一个命令的标准输入(stdin)。通过管道,多个命令可以串联成一条处理流水线,每个命令专注于单一任务,最终完成复杂的操作。
核心特点
- 数据流式处理:数据通过管道逐行传递,无需等待前一个命令完全执行完毕。
- 无中间文件:避免生成临时文件,节省磁盘 I/O 开销。
- 命令组合:通过简单命令的灵活组合,实现复杂功能。
管道的工作原理
- 进程间连接:
当执行命令A | 命令B
时,系统会同时启动两个进程,命令A
的输出直接成为命令B
的输入。
# 示例:生成数据 -> 过滤 -> 排序
cat data.txt | grep "error" | sort
``` - `cat` 读取文件内容并输出。
- `grep` 接收输出并过滤含 "error" 的行。
- `sort` 对过滤后的结果排序。
2. **仅传递标准输出**:
默认情况下,**标准错误(stderr)** 不会通过管道传递。需使用 `2>&1` 合并错误流到标准输出:
```bash
ls /nonexistent 2>&1 | grep "No such file" ```
---
### **管道在文本处理中的主要应用**
#### **1. 多级过滤与转换**
通过管道串联多个工具,逐步处理文本:
```bash
# 统计日志中每个用户的访问次数并排序
cat access.log | awk '{print $1}' | sort | uniq -c | sort -nr
- 分解步骤:
cat
输出日志内容。awk
提取第一列(用户 IP)。sort
排序以准备去重。uniq -c
统计每个 IP 出现次数。sort -nr
按次数降序排列。
2. 实时监控日志
结合 tail -f
实时跟踪日志并处理:
# 实时监控包含 "ERROR" 的日志行,并提取时间戳和消息
tail -f app.log | grep "ERROR" | awk '{print $1, $3}'
3. 数据清洗与格式化
清理不规则文本并转换为结构化数据:
# 清理 CSV 文件:删除空行、替换分隔符、提取指定列
cat raw.csv | sed '/^$/d' | tr ';' ',' | cut -d',' -f1,3-5
sed
删除空行。tr
将分号替换为逗号。cut
提取特定列。
4. 复杂统计与报表生成
组合 awk
和数学工具生成统计结果:
# 计算系统进程的 CPU 使用率总和
ps aux | awk '{sum += $3} END {print "Total CPU Usage:", sum "%"}'
5. 批量文件操作
结合 xargs
处理管道传递的文件列表:
# 查找所有 .txt 文件并压缩
find . -name "*.txt" | xargs tar -czvf backup.tar.gz
管道使用技巧与注意事项
1. 性能优化
- 减少数据量:尽量在管道早期使用
grep
、cut
等工具过滤无关数据,减少后续处理负担。 - 避免过度拆分:某些场景下,使用
awk
单命令完成多步骤比多个管道更高效。
2. 错误处理
- 调试管道:逐步执行管道中的每个命令,确认中间结果是否符合预期。
cat file.txt | tee intermediate.log | grep "key" # 用 tee 保存中间结果
```bash
command1 2>&1 | command2
3. 多行处理
- 处理多行记录:某些工具(如
sed
、awk
)支持多行模式,需调整命令参数。# 合并跨行日志(假设日志以空行分隔) sed -e ':a;N;$!ba;s/\n\t/ /g' log.txt | grep "ERROR"
#### **4. 替代方案**
- **临时文件**:当管道链过长时,可拆分步骤并用临时文件过渡,提高可读性:
```bash
grep "pattern" input.txt > temp1.txt sort temp1.txt > temp2.txt ```
---
### **经典管道组合示例**
#### **1. 统计词频**
```bash
# 统计文本中单词出现频率(Top 10)
cat novel.txt | tr ' ' '\n' | tr -d '.,!?' | sort | uniq -c | sort -nr | head -n 10
2. 网络监控
# 实时监控 HTTP 请求的客户端 IPtail -f /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c
3. 系统管理
# 找出内存占用最高的进程
ps aux | sort -nk 4 | tail -n 5
总结
管道是 Linux 文本处理的核心机制,通过将简单工具组合成流水线,能高效完成过滤、转换、统计等任务。掌握以下关键点可大幅提升效率:
- 工具协同:理解
grep
、sed
、awk
、sort
等工具的输入输出特性。 - 数据流思维:以流式处理减少内存占用,避免中间文件。
- 调试技巧:使用
tee
检查中间结果,逐步构建复杂管道。
20个awk常用场景
以下是 20 个 awk
的常用场景及代码示例,涵盖日志分析、数据提取、统计计算等实际需求:
1. 提取指定列
# 提取 CSV 文件的第 2 列(分隔符为逗号)
awk -F',' '{print $2}' data.csv
# 提取日志文件的第 1 列(默认空格分隔)
awk '{print $1}' access.log
2. 条件过滤行
# 输出第 3 列大于 100 的行
awk '$3 > 100 {print $0}' data.txt
# 输出包含 "ERROR" 的行
awk '/ERROR/ {print}' app.log
3. 统计行数
# 统计文件总行数
awk 'END {print NR}' file.txt
# 统计匹配正则的行数(例如统计 404 状态码)
awk '/ 404 / {count++} END {print count}' access.log
4. 计算列的总和
# 计算第 5 列的总和
awk '{sum += $5} END {print sum}' sales.txt
5. 计算平均值
# 计算第 2 列的平均值
awk '{sum += $2} END {print sum/NR}' data.txt
6. 求最大值/最小值
# 求第 4 列的最大值
awk 'NR==1 {max=$4} $4>max {max=$4} END {print max}' metrics.txt
# 求第 3 列的最小值
awk 'NR==1 {min=$3} $3<min {min=$3} END {print min}' data.txt
7. 修改输出分隔符
# 将空格分隔改为逗号分隔输出
awk 'BEGIN {OFS=","} {print $1, $3, $5}' input.txt
8. 处理多字符分隔符
# 使用正则定义分隔符(例如冒号或逗号)
awk -F'[:,]' '{print $2}' mixed_data.txt
9. 字符串拼接
# 合并第 1 列和第 3 列,用下划线连接
awk '{print $1 "_" $3}' users.txt
10. 格式化输出
# 按格式输出时间戳和用户名(类似日志格式)
awk '{printf "[%s] User: %s\n", strftime("%Y-%m-%d"), $1}' log.txt
11. 去重统计
# 统计第 2 列不同值的出现次数
awk '{count[$2]++} END {for (item in count) print item, count[item]}' data.txt
12. 分组求和
# 按第 1 列分组,求第 3 列的和
awk '{sum[$1] += $3} END {for (key in sum) print key, sum[key]}' sales.csv
13. 处理多文件
# 同时处理多个文件,输出文件名和行号
awk '{print FILENAME ":" FNR "\t" $0}' file1.txt file2.txt
14. 过滤重复行
# 仅输出第一次出现的行(需先排序)
sort data.txt | awk '!seen[$0]++'
15. 提取两个模式之间的行
# 提取从 "START" 到 "END" 之间的行
awk '/START/, /END/' log.txt
16. 替换文本内容
# 替换每行的第一个 "foo" 为 "bar"awk '{sub(/foo/, "bar")} 1' file.txt
# 全局替换 "old" 为 "new"awk '{gsub(/old/, "new")} 1' file.txt
17. 处理固定宽度数据
# 提取第 1-10 字符作为 ID,第 20-25 字符作为金额
awk '{id = substr($0, 1, 10); amount = substr($0, 20, 6); print id, amount}' fixed_width.txt
18. 解析系统命令输出
# 统计每个用户的进程数
ps aux | awk 'NR>1 {count[$1]++} END {for (user in count) print user, count[user]}'
# 统计 TCP 连接状态
netstat -ant | awk '/^tcp/ {state[$6]++} END {for (s in state) print s, state[s]}'
19. 处理时间戳
# 将 Unix 时间戳转换为可读时间
awk '{print strftime("%Y-%m-%d %H:%M:%S", $1)}' timestamps.txt
20. 生成报告
# 生成 CSV 统计报告(带表头)
awk -F',' '
BEGIN {print "Name,Total,Average"} { sum[$1] += $2 count[$1]++ } END { for (name in sum) { avg = sum[name]/count[name] printf "%s,%d,%.2f\n", name, sum[name], avg } }' sales_data.csv
关键技巧总结
- 内置变量:灵活使用
NR
(行号)、NF
(字段数)、FS
(输入分隔符)、OFS
(输出分隔符)。 - 数组统计:利用关联数组(如
count[key]
)实现分组统计。 - 正则匹配:在模式或
sub()
/gsub()
中使用正则表达式。 - 多命令组合:通过管道将
awk
与sort
、uniq
等工具结合使用。
掌握这些场景后,可快速解决日常文本处理中 90% 的问题!