5.4.2 流式编辑与过滤(sed)
流式编辑与过滤(sed)#
1. sed定位与常见场景#
sed(Stream Editor)适用于对文本流进行逐行处理、筛选与替换,常见于日志清洗、批量配置修改、数据格式化、管道链路过滤。其特点是非交互式、支持管道、可脚本化、可原地编辑。
原理草图(流式处理模型):
2. 安装与版本检查#
大多数发行版默认自带 sed;容器与极简系统需显式安装。
安装:
# Debian/Ubuntu
sudo apt update && sudo apt install -y sed
# CentOS/RHEL/Alma/Rocky
sudo yum install -y sed
# Alpine
apk add --no-cache sed
版本确认:
sed --version
# 预期:输出 GNU sed 4.x 或 BusyBox sed 版本信息
3. 基本语法与执行模型#
- 基本格式:
sed [选项] '地址范围{命令}' 文件 - 常用选项:
-n:默认不打印,配合p输出-i:原地编辑(生产慎用)-E:启用扩展正则-f:读取脚本文件
命令解释示例(带预期):
# 准备示例文件
cat > /tmp/app.log <<'EOF'
INFO start
ERROR user=1001 action=login
WARN retry
ERROR user=1002 action=logout
EOF
# 仅打印包含 ERROR 的行
sed -n '/ERROR/p' /tmp/app.log
# 预期输出:
# ERROR user=1001 action=login
# ERROR user=1002 action=logout
# 只打印第2~3行
sed -n '2,3p' /tmp/app.log
4. 常用命令与示例(替换/删除/插入)#
替换:
# 每行仅替换第一个匹配
sed 's/ERROR/ERR/' /tmp/app.log
# 全行替换并屏蔽 user 数字
sed -E 's/(user)=([0-9]+)/\1=*** /g' /tmp/app.log
删除:
# 删除首行
sed '1d' /tmp/app.log
# 删除空行与注释行
cat > /tmp/app.conf <<'EOF'
# comment
PORT=8080
DEBUG=true
EOF
sed '/^#/d;/^$/d' /tmp/app.conf
插入与追加:
# 第1行前插入标题
sed '1i\title=APP' /tmp/app.conf
# 第3行后追加一行
sed '3a\TIMEOUT=30' /tmp/app.conf
5. 正则与转义要点#
- 基本正则中
+、?需转义;-E启用扩展正则 - 分隔符冲突可用其它符号:
sed 's#/usr/local#/opt#g' - 行首行尾:
^、$ - 反向引用:基本正则
\(\)与\1;扩展正则()
示例:替换路径分隔符
echo "/usr/local/bin" | sed 's#/usr/local#/opt#g'
# 预期:/opt/bin
6. 典型运维用法(含完整链路)#
批量修改配置并备份:
# 原地修改并生成 .bak 备份
sed -i.bak 's/^PORT=.*/PORT=8080/' /etc/myapp/app.conf
# 预期:/etc/myapp/app.conf 被修改,/etc/myapp/app.conf.bak 保留旧值
提取区间日志:
# 从时间段日志中提取
sed -n '/2024-01-01 00:00/,/2024-01-01 01:00/p' /var/log/app.log
清理空行并统一分隔符:
# 输入文件
cat > /tmp/data.txt <<'EOF'
a,b,c
1,2,3
EOF
# 删除空行并将全角逗号替换为半角
sed '/^$/d;s/,/,/g' /tmp/data.txt
# 预期:
# a,b,c
# 1,2,3
7. 与管道组合的惯用模式#
grep + sed 精准取样:
grep ERROR /tmp/app.log | sed -n '1,1p'
# 解释:先筛 ERROR,再取第一行
sed + awk 清洗字段:
# 将 | 转空格后取第1与第3字段
echo "u01|ok|200" | sed 's/|/ /g' | awk '{print $1,$3}'
# 预期:u01 200
8. 排错与最佳实践#
常见问题与排查:
1. -i 无效或报错:BusyBox sed 不支持 -i.bak 写法
解决:
bash
# BusyBox 环境采用:
sed -i 's/old/new/' file
2. 替换没生效:正则未匹配或行首行尾未考虑
排查:
bash
sed -n '/pattern/p' file # 先验证匹配
3. 大量输出:忘记使用 -n
解决:
bash
sed -n '1,5p' file
最佳实践:
- 原地修改前备份:sed -i.bak 's/old/new/g' file
- 复杂处理写脚本文件,便于版本管理:
cat > /tmp/rules.sed <<'EOF'
/^#/d
/^$/d
s/ERROR/ERR/g
EOF
sed -f /tmp/rules.sed /tmp/app.log
9. 练习(含答案提示)#
- 练习1:删除
/tmp/app.log中所有WARN行并打印前2行
参考命令:
bash sed '/WARN/d' /tmp/app.log | sed -n '1,2p' - 练习2:将
user=数字替换为user=***
参考命令:
bash sed -E 's/user=[0-9]+/user=***/g' /tmp/app.log - 练习3:将配置文件中
DEBUG=false改为DEBUG=true并备份
参考命令:
bash sed -i.bak 's/^DEBUG=false$/DEBUG=true/' /tmp/app.conf