sed 是 Linux 文本处理的三驾马车之一.
sed(Stream Editor,流编辑器)是 Linux/Unix 系统中一个强大的文本处理工具。它不像 Vim 或 Nano 那样需要交互式地打开文件进行编辑,而是通过预先定义好的规则(脚本),对文本流(文件或管道输入)进行非交互式的读取、编辑和输出。这使得它非常适合在脚本和自动化任务中处理文本。
1. 核心工作机制:模式空间与保持空间
理解 sed 的工作方式是掌握它的关键。sed 维护着两个缓冲区:
1. 模式空间(Pattern Space):这是 sed 的核心缓冲区。sed 从输入流中读取一行,移除尾部的换行符,并将其放入模式空间。然后,对该缓冲区的内容执行用户指定的命令。处理完成后,默认情况下会将缓冲区的内容(可能已被修改)输出到标准输出,并清空缓冲区,接着读取下一行,开始新的循环。
2. 保持空间(Hold Space):这是一个长期的、辅助性的缓冲区。sed 在处理当前行时,可以将模式空间的内容暂存到这里,或者将这里的内容取回模式空间。这在处理跨行、复杂的文本变换时非常有用,相当于一个“剪贴板”。
2. 基本命令语法
sed [选项] '脚本' [输入文件]
· 选项:用于控制 sed 的运行方式。
· 脚本:由地址定界和命令组成,例如 's/old/new/g' 是一个替换脚本。如果脚本较复杂,可以用 -e 选项连接多个脚本,或用 -f 从文件中读取脚本。
· 输入文件:要处理的文本文件。如果不指定,则从标准输入读取。
3. 核心操作详解(附常用命令表)
sed 的命令非常丰富,以下是一些最核心的用法,通过表格可以更清晰地查阅:
命令类别 命令语法示例 功能描述
替换 s/// sed 's/foo/bar/g' file将每行所有的"foo替换为 "bar"
s/// sed -n 's/foo/bar/p' file 只打印发生替换的行。
s/// sed '3s/foo/bar/' file 只替换第3行中的第一个"foo"
s/// sed 's/foo/bar/2'file只替换每行中第二个出现的 "foo"
删除 d sed '3d' file 删除第3行。
d sed '2,5d' file 删除第2到5行。
d sed '/^#/d' file 删除所有以 "#" 开头的行(删除注释)
d sed '/^$/d' file 删除所有空行。
打印 p sed -n '5p' file 仅打印第5行。
p sed -n '/error/p' file 仅打印包含 "error" 的行。
p sed -n '10,20p' file 仅打印第10到20行。
插入追加 i\ sed '3i\Hello' file在第3行之前插入一行"Hello"。
a\ sed '5a\World' file 在第5行之后追加一行"World"。
c\ sed '3c\New Line' file 用 "New Line" 替换第3行。
文件读写 r sed '$r other.txt' file 在 file 的最后一行后,读取 并追加 other.txt 的内容。
w sed '/pattern/w output.txt' file 将 file 中匹配 "pattern" 的行写入到 output.txt。
保持空间 h sed '/pattern/h' file 将匹配行的模式空间内容
复制到保持空间。
H sed '/pattern/H' file 将匹配行的模式空间内容追 加到保持空间。
g sed '/pattern/g' file 将保持空间的内容复制回模式 空间。
G sed '/pattern/G' file 将保持空间的内容追加到模式 空间。
x sed 'x' file 交换模式空间和保持空间的内容。
流程控制 b sed '/start/b label; s/.../.../' 无条件下跳转到 :label 处执行。
t sed 's/.../.../; t label; ...' 若之前的 s/// 替换成功, 则跳转到 :label。
: label sed ':a; s/.../.../; ta' 定义一个标签 label,供 b 或 t 命令跳转。
4. 地址定界
命令前面可以指定地址,用于限定命令的作用范围。
地址类型 示例 描述
行号 3 指定第3行。
行号范围 2,5 指定从第2行到第5行的范围。
步长地址 1~2 从第1行开始,每隔2行,即所有奇数行。
最后一行 $ 文件的最后一行。
正则表达式 /^root/ 匹配所有以 "root" 开头的行。
正则范围 /start/,/end/ 从第一次匹配到 "start" 的行开始,到 第一次匹配到 "end" 的行结束(包含这两行)。
混合范围 /pattern/,+3 从匹配到 "pattern" 的行开始,到该行 之后的3行。
否定 /pattern/! 在所有不匹配 "pattern" 的行上执行命令。
5. 常用选项详解
选项 描述及示例
-n 静默模式。禁止 sed 的默认输出(即打印模式空间的内 容)。通常与 p 命令配合,只打印我们感兴趣的行。 sed -n '2,4p' file.txt
-i 直接修改文件。默认情况下,sed 只将修改后的结果输出 到屏幕,原文件不变。使用 -i 会直接将修改写回原文件。 操作前务必确认脚本正确,或配合后缀进行备份。
sed -i.bak 's/old/new/g' file.txt(修改前会创建 file.txt.bak 备份)
-e 多点编辑。允许在同一行执行多个 sed 命令。
sed -e 's/foo/bar/' -e 's/baz/qux/' file.txt
-f 从文件读取脚本。当命令序列较长时,可以写入文件,然 后用 -f 调用。
sed -f script.sed file.txt
-E / -r 使用扩展正则表达式。默认 sed 使用基础正则表达式 (BRE),一些元字符(如 +, ?, ` , ())需要转义。使用 -E` 后,语法更简洁、现代[citation:1][citation:2] [citation:4]。
6. 正则表达式支持
sed 的核心是模式匹配,这离不开正则表达式。
· 基础正则表达式(BRE):默认使用。元字符如 {, }, (, ), +, ? 等需要加反斜杠 \ 才能拥有特殊含义。
· 扩展正则表达式(ERE):通过 -E 或 -r 选项启用。元字符无需转义,语法更清晰。
7. 实际应用示例
批量修改配置文件:将 Nginx 配置中所有以 # 开头的注释行删除,并将 listen 80; 替换为 listen 443 ssl;,直接修改文件并创建备份。
sed -i.bak -e '/^#/d' -e 's/listen 80;/listen 443 ssl;/' /etc/nginx/sites-available/default
日志过滤与格式化:从 Apache 日志中提取所有 404 错误的 IP 地址和请求路径。
sed -n '/ 404 / s/^\([0-9.]*\).*"\(.*\)"$/\1 - \2/p' access.log
数据清洗:将 CSV 文件中的分隔符由逗号替换为制表符,并删除含有 NULL 的行。
sed -e 's/,/\t/g' -e '/NULL/d' data.csv > clean_data.tsv
总结
sed 是 Linux 文本处理的三驾马车(grep、sed、awk)之一。它非交互式和流式处理的特点,使其在批量处理、数据清洗、脚本自动化方面拥有极高的效率和无可替代的地位。从简单的查找替换到复杂的跨行编辑,掌握 sed 能让你在命令行世界中的文本处理能力得到质的提升。