文本处理 #
一、grep - 文本搜索 #
1.1 基本用法 #
bash
# 基本搜索
grep "pattern" file.txt
# 搜索多个文件
grep "pattern" file1.txt file2.txt
# 递归搜索目录
grep -r "pattern" directory/
# 从标准输入搜索
cat file.txt | grep "pattern"
1.2 常用选项 #
| 选项 | 说明 |
|---|---|
| -i | 忽略大小写 |
| -v | 反向匹配 |
| -n | 显示行号 |
| -c | 只显示匹配行数 |
| -l | 只显示文件名 |
| -L | 显示不匹配的文件名 |
| -w | 匹配整个单词 |
| -x | 匹配整行 |
| -r | 递归搜索 |
| -E | 使用扩展正则表达式 |
| -F | 固定字符串匹配 |
| -P | 使用 Perl 正则表达式 |
| –color | 高亮显示匹配 |
1.3 正则表达式 #
基本正则表达式(BRE):
bash
# 匹配行首
grep "^start" file.txt
# 匹配行尾
grep "end$" file.txt
# 匹配任意单个字符
grep "a.c" file.txt
# 匹配零个或多个
grep "ab*c" file.txt
# 匹配字符集
grep "[abc]" file.txt
grep "[a-z]" file.txt
grep "[^abc]" file.txt
# 转义字符
grep "\." file.txt
扩展正则表达式(ERE):
bash
# 使用 -E 选项
grep -E "pattern" file.txt
# 或
egrep "pattern" file.txt
# 匹配一次或多次
grep -E "ab+c" file.txt
# 匹配零次或一次
grep -E "ab?c" file.txt
# 匹配 N 次
grep -E "a{3}" file.txt
grep -E "a{2,4}" file.txt
# 分组
grep -E "(ab)+" file.txt
# 或运算
grep -E "cat|dog" file.txt
1.4 实用示例 #
bash
# 搜索进程
ps aux | grep nginx
# 搜索日志中的错误
grep -i "error\|warning" /var/log/syslog
# 搜索 IP 地址
grep -E "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" file.txt
# 搜索邮箱
grep -E "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}" file.txt
# 搜索手机号
grep -E "1[3-9][0-9]{9}" file.txt
# 统计代码行数(排除空行和注释)
grep -v "^$\|^#" file.txt | wc -l
# 搜索多个关键词
grep -E "error|warning|fail" /var/log/syslog
# 显示匹配上下文
grep -C 5 "error" /var/log/syslog
# 只显示匹配部分
grep -oE "[0-9]+" file.txt
二、sed - 流编辑器 #
2.1 基本语法 #
bash
sed [选项] '命令' 文件
2.2 常用选项 #
| 选项 | 说明 |
|---|---|
| -n | 只输出处理后的行 |
| -e | 执行多个命令 |
| -f | 从文件读取命令 |
| -i | 直接修改文件 |
| -r | 使用扩展正则表达式 |
2.3 常用命令 #
替换命令:
bash
# 替换每行第一个匹配
sed 's/old/new/' file.txt
# 替换所有匹配
sed 's/old/new/g' file.txt
# 替换第 N 个匹配
sed 's/old/new/2' file.txt
# 只打印替换的行
sed -n 's/old/new/p' file.txt
# 忽略大小写
sed 's/old/new/gi' file.txt
# 直接修改文件
sed -i 's/old/new/g' file.txt
# 备份后修改
sed -i.bak 's/old/new/g' file.txt
删除命令:
bash
# 删除第 N 行
sed '3d' file.txt
# 删除第 M 到 N 行
sed '2,5d' file.txt
# 删除最后一行
sed '$d' file.txt
# 删除匹配行
sed '/pattern/d' file.txt
# 删除空行
sed '/^$/d' file.txt
# 删除注释行
sed '/^#/d' file.txt
插入和追加:
bash
# 在第 N 行前插入
sed '3i\new line' file.txt
# 在第 N 行后追加
sed '3a\new line' file.txt
# 在匹配行前插入
sed '/pattern/i\new line' file.txt
# 在匹配行后追加
sed '/pattern/a\new line' file.txt
# 在文件开头插入
sed '1i\header' file.txt
# 在文件末尾追加
sed '$a\footer' file.txt
打印命令:
bash
# 打印第 N 行
sed -n '3p' file.txt
# 打印第 M 到 N 行
sed -n '2,5p' file.txt
# 打印匹配行
sed -n '/pattern/p' file.txt
# 打印奇数行
sed -n '1~2p' file.txt
# 打印偶数行
sed -n '2~2p' file.txt
2.4 高级用法 #
使用变量:
bash
# 使用 shell 变量
var="pattern"
sed "s/$var/new/g" file.txt
# 使用正则分组
sed -r 's/([a-z]+) ([0-9]+)/\2 \1/' file.txt
多命令执行:
bash
# 使用 -e 执行多个命令
sed -e 's/old/new/g' -e 's/foo/bar/g' file.txt
# 使用分号分隔
sed 's/old/new/g; s/foo/bar/g' file.txt
# 使用 {} 分组
sed '{s/old/new/g; s/foo/bar/g}' file.txt
条件执行:
bash
# 只在匹配行执行
sed '/pattern/s/old/new/g' file.txt
# 不匹配时执行
sed '/pattern/!s/old/new/g' file.txt
2.5 实用示例 #
bash
# 删除 HTML 标签
sed 's/<[^>]*>//g' file.html
# 删除行首空格
sed 's/^[ \t]*//' file.txt
# 删除行尾空格
sed 's/[ \t]*$//' file.txt
# 添加行号
sed = file.txt | sed 'N;s/\n/\t/'
# 提取 IP 地址
sed -nE 's/.*([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*/\1/p' file.txt
# 批量替换文件内容
find . -name "*.txt" -exec sed -i 's/old/new/g' {} +
# 配置文件修改
sed -i 's/^Port 22/Port 2222/' /etc/ssh/sshd_config
三、awk - 文本处理语言 #
3.1 基本语法 #
bash
awk 'pattern { action }' file.txt
3.2 内置变量 #
| 变量 | 说明 |
|---|---|
| $0 | 整行内容 |
| $1-$n | 第 n 个字段 |
| NF | 字段数量 |
| NR | 行号(所有文件) |
| FNR | 行号(当前文件) |
| FS | 输入字段分隔符 |
| OFS | 输出字段分隔符 |
| RS | 输入记录分隔符 |
| ORS | 输出记录分隔符 |
| FILENAME | 当前文件名 |
3.3 基本用法 #
打印字段:
bash
# 打印第一列
awk '{print $1}' file.txt
# 打印多列
awk '{print $1, $3}' file.txt
# 打印整行
awk '{print $0}' file.txt
# 打印最后一列
awk '{print $NF}' file.txt
# 打印倒数第二列
awk '{print $(NF-1)}' file.txt
# 自定义分隔符
awk -F: '{print $1}' /etc/passwd
awk -F',' '{print $1, $2}' file.csv
条件过滤:
bash
# 打印匹配行
awk '/pattern/' file.txt
# 打印不匹配行
awk '!/pattern/' file.txt
# 条件判断
awk '$3 > 100' file.txt
awk '$1 == "root"' /etc/passwd
# 组合条件
awk '$3 > 100 && $3 < 200' file.txt
awk '$1 == "root" || $1 == "nobody"' /etc/passwd
格式化输出:
bash
# 使用 printf
awk '{printf "%-10s %5d\n", $1, $2}' file.txt
# 添加表头
awk 'BEGIN{print "Name\tScore"} {print $1"\t"$2}' file.txt
# 添加行号
awk '{print NR, $0}' file.txt
3.4 高级用法 #
BEGIN 和 END:
bash
# BEGIN 块在处理前执行
awk 'BEGIN{FS=":"; print "Users:"} {print $1}' /etc/passwd
# END 块在处理后执行
awk 'END{print "Total lines:", NR}' file.txt
# 计算总和
awk '{sum+=$1} END{print "Sum:", sum}' file.txt
# 计算平均值
awk '{sum+=$1} END{print "Average:", sum/NR}' file.txt
数组操作:
bash
# 统计出现次数
awk '{count[$1]++} END{for(i in count) print i, count[i]}' file.txt
# 统计单词频率
awk '{for(i=1;i<=NF;i++) count[$i]++} END{for(word in count) print word, count[word]}' file.txt
流程控制:
bash
# if 语句
awk '{if($3>100) print $1, "large"; else print $1, "small"}' file.txt
# for 循环
awk '{for(i=1;i<=NF;i++) print $i}' file.txt
# while 循环
awk '{i=1; while(i<=NF) {print $i; i++}}' file.txt
3.5 实用示例 #
bash
# 统计日志中各 IP 访问次数
awk '{print $1}' access.log | sort | uniq -c | sort -nr | head -10
# 分析 Nginx 访问日志
awk '{print $1, $7}' access.log
# 提取特定列并排序
awk -F: '{print $1}' /etc/passwd | sort
# 计算文件大小总和
ls -l | awk '{sum+=$5} END{print "Total:", sum/1024/1024, "MB"}'
# 查找大文件
ls -lh | awk '$5 ~ /G$/ {print $9, $5}'
# 统计代码行数
awk 'END{print NR}' file.txt
# 提取 JSON 数据
awk -F'"' '{print $4}' data.json
# 格式化输出表格
awk 'BEGIN{printf "%-20s %-10s\n", "Name", "Score"} {printf "%-20s %-10d\n", $1, $2}' file.txt
四、其他文本工具 #
4.1 cut - 切割文本 #
bash
# 按字符切割
cut -c 1-5 file.txt
cut -c 1,3,5 file.txt
# 按字段切割
cut -d: -f1 /etc/passwd
cut -d',' -f1,3 file.csv
# 按字节切割
cut -b 1-10 file.txt
4.2 sort - 排序 #
bash
# 默认排序
sort file.txt
# 反向排序
sort -r file.txt
# 数字排序
sort -n file.txt
# 按列排序
sort -k2 file.txt
sort -k2 -n file.txt
# 去重排序
sort -u file.txt
# 检查是否已排序
sort -c file.txt
# 随机排序
sort -R file.txt
# 按月份排序
sort -M file.txt
4.3 uniq - 去重 #
bash
# 去除连续重复行
uniq file.txt
# 显示重复次数
uniq -c file.txt
# 只显示重复行
uniq -d file.txt
# 只显示不重复行
uniq -u file.txt
# 忽略大小写
uniq -i file.txt
# 组合使用
sort file.txt | uniq -c | sort -nr
4.4 tr - 字符转换 #
bash
# 字符替换
tr 'a-z' 'A-Z' < file.txt
# 删除字符
tr -d '0-9' < file.txt
# 压缩重复字符
tr -s ' ' < file.txt
# 删除非指定字符
tr -d -c '0-9' < file.txt
# 示例
echo "hello world" | tr 'a-z' 'A-Z'
echo "192.168.1.1" | tr '.' ' '
4.5 paste - 合并文件 #
bash
# 按行合并
paste file1.txt file2.txt
# 指定分隔符
paste -d',' file1.txt file2.txt
# 合并为单列
paste -s file.txt
4.6 join - 连接文件 #
bash
# 连接两个文件
join file1.txt file2.txt
# 指定字段
join -1 1 -2 2 file1.txt file2.txt
# 指定分隔符
join -t',' file1.txt file2.txt
4.7 split - 分割文件 #
bash
# 按行数分割
split -l 1000 file.txt
# 按大小分割
split -b 10M file.txt
# 指定前缀
split -l 1000 file.txt part_
# 数字后缀
split -d -l 1000 file.txt part_
五、实践练习 #
5.1 练习一:grep 搜索 #
bash
# 1. 创建测试文件
cat > test.log << EOF
2024-03-27 10:00:00 INFO Application started
2024-03-27 10:01:00 ERROR Connection failed
2024-03-27 10:02:00 WARNING Memory usage high
2024-03-27 10:03:00 ERROR Database timeout
2024-03-27 10:04:00 INFO User login
EOF
# 2. 搜索错误日志
grep "ERROR" test.log
# 3. 统计错误数量
grep -c "ERROR" test.log
# 4. 搜索 ERROR 或 WARNING
grep -E "ERROR|WARNING" test.log
5.2 练习二:sed 替换 #
bash
# 1. 替换日期格式
sed 's/2024-03-27/2024/03/27/' test.log
# 2. 删除时间列
sed 's/[0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\} //' test.log
# 3. 提取日志级别
sed -nE 's/.* (INFO|ERROR|WARNING) .*/\1/p' test.log
5.3 练习三:awk 处理 #
bash
# 1. 提取时间和级别
awk '{print $1, $2, $3}' test.log
# 2. 统计各级别数量
awk '{count[$3]++} END{for(i in count) print i, count[i]}' test.log
# 3. 提取错误信息
awk '/ERROR/ {print $0}' test.log
5.4 练习四:综合应用 #
bash
# 1. 分析访问日志
awk '{print $1}' access.log | sort | uniq -c | sort -nr | head -10
# 2. 提取配置文件中的非注释行
grep -v "^#\|^$" /etc/nginx/nginx.conf
# 3. 格式化 CSV 文件
awk -F',' '{printf "%-20s %-10s\n", $1, $2}' data.csv
六、小结 #
本章学习了 Linux 文本处理三剑客 grep、sed、awk 以及其他文本处理工具。
关键要点:
- grep 用于文本搜索,支持正则表达式
- sed 用于流编辑,适合批量替换
- awk 是强大的文本处理语言
- 组合使用可以完成复杂的文本处理任务
- 掌握正则表达式是文本处理的关键
下一章预告: 进程管理 - 学习进程查看、控制和管理命令。
最后更新:2026-03-27