文本处理 #

一、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 以及其他文本处理工具。

关键要点:

  1. grep 用于文本搜索,支持正则表达式
  2. sed 用于流编辑,适合批量替换
  3. awk 是强大的文本处理语言
  4. 组合使用可以完成复杂的文本处理任务
  5. 掌握正则表达式是文本处理的关键

下一章预告: 进程管理 - 学习进程查看、控制和管理命令。

最后更新:2026-03-27