LarryDpk
发布于 2025-04-14 / 10 阅读
0

Linux处理文本

Linux处理文本

Linux 文本处理工具

Linux 系统提供了大量强大且灵活的文本处理工具,以下是常用的分类整理及典型用法示例:


一、查看与浏览工具

  1. cat
  • 查看文件内容或合并文件。
  • 示例:cat file.txt
  • 替代工具:bat(支持语法高亮、分页)。
  1. less / more
  • 分页查看大文件(支持上下翻页)。
  • 示例:less large.log
  1. head / tail
  • 查看文件头部或尾部内容。
  • 示例:tail -n 100 error.log(显示最后100行)。

二、搜索与过滤工具

  1. grep
  • 按正则表达式搜索文本。
  • 示例:grep "error" log.txt(查找含 “error” 的行)。
  • 替代工具:ripgrep (rg)(更快,支持 .gitignore)。
  1. ack / ag
  • 针对代码的增强搜索工具(自动忽略版本控制文件)。
  • 示例:ag "function_name" src/

三、处理与转换工具

  1. sed
  • 流编辑器,用于替换、删除、插入文本。
  • 示例:sed 's/foo/bar/g' file.txt(全局替换 foo 为 bar)。
  1. awk
  • 强大的文本分析工具,支持字段处理。
  • 示例:awk '{print $1}' data.txt(输出第一列)。
  1. cut
  • 按列切割文本。
  • 示例:cut -d',' -f1-3 data.csv(提取 CSV 文件的前三列)。
  1. tr
  • 字符替换或删除。
  • 示例:tr 'a-z' 'A-Z' < file.txt(转大写)。
  1. sort
  • 排序文本行。
  • 示例:sort -n data.txt(按数值排序)。
  1. uniq
  • 去重相邻重复行(常与 sort 结合)。
  • 示例:sort file.txt | uniq -c(统计重复次数)。

四、统计与分析工具

  1. wc
  • 统计行数、单词数、字节数。
  • 示例:wc -l access.log(统计行数)。
  1. paste
  • 合并文件列。
  • 示例:paste file1.txt file2.txt(按列合并)。
  1. join
  • 按共同字段连接两个文件(类似 SQL JOIN)。
  • 示例:join file1.txt file2.txt

五、替换与编辑工具

  1. perl
  • 支持复杂正则替换(常用于一行命令)。
  • 示例:perl -pi -e 's/old/new/g' *.txt(批量替换文件内容)。
  1. vim / ex
  • 交互式文本编辑(ex 适合脚本化操作)。
  • 示例:ex -sc '%s/foo/bar/g|x' file.txt(非交互式替换)。

六、结构化文本处理

  1. jq
  • 解析和操作 JSON 数据。
  • 示例:curl API | jq '.data[].name'
  1. yq
  • 处理 YAML/XML/JSON 文件(类似 jq 的功能)。
  • 示例:yq '.key.subkey' config.yaml
  1. xmlstarlet
  • XML 解析和转换工具。
  • 示例:xmlstarlet sel -t -v "//title" file.xml

七、多文件与差异处理

  1. diff
  • 比较文件差异。
  • 示例:diff file1.txt file2.txt
  1. patch
  • 应用差异文件。
  • 示例:patch original.txt < diff.patch
  1. comm
  • 比较两个有序文件的异同。
  • 示例:comm file1.txt file2.txt

八、其他实用工具

  1. column
  • 格式化文本为表格。
  • 示例:ps aux | column -t(对齐进程信息)。
  1. fmt
  • 文本段落格式化。
  • 示例:fmt -w 80 long_text.txt(设置每行80字符)。
  1. 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:处理结构化数据,支持复杂逻辑和计算。

学习建议

  1. 先掌握 grep 的正则表达式和常用参数。
  2. 熟悉 sed 的替换 (s///) 和删除 (d) 命令。
  3. 学习 awk 的字段操作和统计技巧。
  4. 通过管道 (|) 组合三者,解决实际问题。

它们的组合能覆盖 90% 的日常文本处理需求,是 Linux 工程师的必备技能!

管道


管道(Pipe)的基本概念

在 Linux 中,管道(符号为 |)是一种进程间通信机制,允许将一个命令的标准输出(stdout)直接传递给另一个命令的标准输入(stdin)。通过管道,多个命令可以串联成一条处理流水线,每个命令专注于单一任务,最终完成复杂的操作。

核心特点

  1. 数据流式处理:数据通过管道逐行传递,无需等待前一个命令完全执行完毕。
  2. 无中间文件:避免生成临时文件,节省磁盘 I/O 开销。
  3. 命令组合:通过简单命令的灵活组合,实现复杂功能。

管道的工作原理

  1. 进程间连接
    当执行 命令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  
  • 分解步骤
    1. cat 输出日志内容。
    2. awk 提取第一列(用户 IP)。
    3. sort 排序以准备去重。
    4. uniq -c 统计每个 IP 出现次数。
    5. 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. 性能优化

  • 减少数据量:尽量在管道早期使用 grepcut 等工具过滤无关数据,减少后续处理负担。
  • 避免过度拆分:某些场景下,使用 awk 单命令完成多步骤比多个管道更高效。

2. 错误处理

  • 调试管道:逐步执行管道中的每个命令,确认中间结果是否符合预期。
    cat file.txt | tee intermediate.log | grep "key"   # 用 tee 保存中间结果  
    
 ```bash  
 command1 2>&1 | command2  

3. 多行处理

  • 处理多行记录:某些工具(如 sedawk)支持多行模式,需调整命令参数。
    # 合并跨行日志(假设日志以空行分隔)  
    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 文本处理的核心机制,通过将简单工具组合成流水线,能高效完成过滤、转换、统计等任务。掌握以下关键点可大幅提升效率:

  1. 工具协同:理解 grepsedawksort 等工具的输入输出特性。
  2. 数据流思维:以流式处理减少内存占用,避免中间文件。
  3. 调试技巧:使用 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  

关键技巧总结

  1. 内置变量:灵活使用 NR(行号)、NF(字段数)、FS(输入分隔符)、OFS(输出分隔符)。
  2. 数组统计:利用关联数组(如 count[key])实现分组统计。
  3. 正则匹配:在模式或 sub()/gsub() 中使用正则表达式。
  4. 多命令组合:通过管道将 awksortuniq 等工具结合使用。

掌握这些场景后,可快速解决日常文本处理中 90% 的问题!