1. Shell脚本中的sed命令概述
sed(Stream Editor)是Linux/Unix系统中一个强大的流式文本编辑器,它通过简洁的命令实现对文本的非交互式编辑。与vim等交互式编辑器不同,sed特别适合在脚本中进行批量文本处理。RHCSE认证考试中,sed是Shell脚本部分的重点考察对象,主要测试考生对文本模式匹配和转换的掌握程度。
我第一次在生产环境使用sed是为了批量修改500多台服务器的配置文件。当时需要将所有的"Timeout=300"改为"Timeout=600",手动操作根本不现实。sed配合for循环只用一行命令就解决了问题,这让我深刻体会到它的威力。
注意:sed默认不会直接修改原文件,而是将处理结果输出到标准输出。要直接修改文件需要显式使用-i选项。
2. sed基础语法与工作模式
2.1 基本命令格式
sed的标准调用格式如下:
sed [选项] '地址范围/操作命令/参数' 文件名一个实际的替换示例:
# 将file.txt中所有的"old"替换为"new" sed 's/old/new/g' file.txt选项部分常用的有:
-n:静默模式,只输出处理过的行-i:直接修改文件内容(危险但实用)-e:连接多个编辑命令
2.2 地址范围详解
sed的强大之处在于它可以精确控制处理哪些行:
- 单行处理:
sed '5s/pattern/replace/' file # 只处理第5行- 行范围处理:
sed '10,20s/pattern/replace/' file # 处理10到20行- 模式匹配:
sed '/start/,/end/s/pattern/replace/' file # 处理从包含"start"到包含"end"的所有行- 步进选择:
sed '1~2s/pattern/replace/' file # 处理所有奇数行(1,3,5...)2.3 常见操作命令
| 命令 | 功能 | 示例 |
|---|---|---|
| s | 替换 | s/old/new/g |
| p | 打印 | 5p (打印第5行) |
| d | 删除 | /pattern/d |
| a | 追加 | 5a\text (在第5行后追加) |
| i | 插入 | /pattern/i\text (在匹配行前插入) |
| c | 整行替换 | /pattern/c\newline |
3. sed高级应用技巧
3.1 分组与反向引用
sed支持使用\(\)进行分组匹配,并通过\1,\2等引用:
# 将"姓 名"格式改为"名, 姓" echo "张 三" | sed 's/\([^ ]*\) \([^ ]*\)/\2, \1/' # 输出:三, 张这个技巧在重排日志格式时特别有用。我曾经用这个功能将Apache日志从通用日志格式(CLF)转换为组合日志格式(Combined)。
3.2 多命令组合
使用-e可以组合多个命令,或者用分号分隔:
# 两种多命令组合方式 sed -e 's/foo/bar/' -e 's/baz/qux/' file sed 's/foo/bar/; s/baz/qux/' file更复杂的例子:同时执行替换和删除
# 将包含"error"的行中的"old"替换为"new",并删除所有空行 sed '/error/s/old/new/g; /^$/d' logfile3.3 保持空间与模式空间
sed有两个缓冲区:
- 模式空间:处理当前行的临时工作区
- 保持空间:长期存储的缓冲区
相关命令:
- h/H:将模式空间复制/追加到保持空间
- g/G:将保持空间复制/追加到模式空间
- x:交换两个空间内容
示例:反转文件行序
sed -n '1!G;h;$p' file.txt4. 实战案例解析
4.1 日志文件处理
处理Nginx访问日志,提取特定时间段的请求:
# 提取2023-01-15 14:00到15:00的日志 sed -n '/15\/Jan\/2023:14:[0-5][0-9]:[0-5][0-9]/,/15\/Jan\/2023:15:[0-5][0-9]:[0-5][0-9]/p' access.log4.2 配置文件批量修改
批量修改多台服务器的SSH配置:
# 禁用root登录并修改端口 sed -i 's/^#PermitRootLogin.*/PermitRootLogin no/; s/^#Port 22/Port 2222/' /etc/ssh/sshd_config4.3 数据清洗与转换
清理CSV文件中的非法字符:
# 移除所有非打印字符,将多个连续逗号变为单个 sed -e 's/[[:cntrl:]]//g' -e 's/,,\+/,/g' data.csv > clean.csv5. 常见问题与解决方案
5.1 特殊字符处理
处理包含斜杠的字符串时,可以使用其他分隔符:
# 替换路径中的/usr/local为/opt sed 's|/usr/local|/opt|g' config.file5.2 性能优化技巧
处理大文件时:
- 尽量使用地址范围缩小处理范围
- 避免不必要的分组和反向引用
- 将多个操作合并到一个sed命令中
5.3 备份策略
使用-i选项时,建议同时指定备份后缀:
# 修改文件并自动创建.bak备份 sed -i.bak 's/old/new/' file6. RHCSE考试重点解析
根据多年经验,RHCSE考试中sed部分常考:
- 基本替换操作(s命令)
- 行寻址技巧(数字范围、模式匹配)
- 多命令组合使用
- 文件原地修改(-i选项)
- 分组和反向引用
典型考题示例: "将/etc/passwd中所有用户的shell从/bin/bash改为/bin/sh,但保留root用户不变"
解决方案:
sed '/^root/!s/\/bin\/bash$/\/bin\/sh/' /etc/passwd7. 个人实战经验分享
在多年的Linux系统管理工作中,我总结了几个sed的黄金法则:
先测试再修改:永远先不加
-i运行命令,确认输出符合预期后再实际修改文件使用版本控制:对重要配置文件的修改,即使使用sed也应该先提交到git或备份
注释复杂命令:在脚本中使用复杂sed命令时,一定要添加注释说明其作用
性能考量:处理超过100MB的文件时,考虑使用awk或专门工具替代
一个真实案例:有次我需要从数千个HTML文件中提取特定div内容。最初尝试用sed,但当文件很大时性能很差。后来改用:
# 对小文件使用sed sed -n '/<div id="content">/,/<\/div>/p' file.html # 对大文件改用专门的HTML解析工具这个经验告诉我:工具要因地制宜,sed虽强但不是万能的。