sed 命令用法解析

一、概述

sed(Stream Editor,流编辑器)是Unix/Linux系统中强大的文本处理工具,主要用于对文本进行查找、替换、插入、删除等操作。其核心特点是:

  • 流式处理:逐行读取输入(文件或管道数据),按指定规则处理后输出。
  • 非破坏性:默认仅修改输出内容,不改变原始文件(需-i选项强制修改)。
  • 支持正则:结合正则表达式实现复杂模式匹配,支持基础正则和扩展正则(需-r选项)。

二、基本语法

sed [选项] '指令' [文件...]

常用选项

选项 作用
-n 抑制默认输出(仅打印匹配/处理的行)
-i 直接修改原始文件(建议配合备份:-i.bak保留原文件为.bak
-r 启用扩展正则表达式(无需转义`(){}?+
-e 支持多个指令组合执行

三、核心功能与示例

1. 查找(打印特定内容)

通过-n(抑制默认输出)和p(打印)指令实现精准查找,支持行号匹配内容匹配

(1)按行号查找

# 打印第2行
sed -n '2p' test.txt

# 打印第2-5行
sed -n '2,5p' test.txt

# 打印第2行和第5行(分号分隔多个指令)
sed -n '2p;5p' test.txt

(2)按内容查找

# 打印包含"ccc"的行
sed -n '/ccc/p' test.txt

# 打印从"aaa"首次出现到"ccc"首次出现之间的行
sed -n '/aaa/,/ccc/p' test.txt

# 同时打印包含"aaa"和"ccc"的行
sed -n '/aaa/p;/ccc/p' test.txt

2. 新增(插入/追加文本)

通过i(行前插入)、a(行后追加)、c(替换整行)指令添加内容。

(1)指定行位置新增

# 在第1行前插入"why"
sed '1iwhy' test.txt

# 在最后一行前插入"why"($表示末尾)
sed '$iwhy' test.txt

# 在最后一行后追加"why"
sed '$awhy' test.txt

# 将第2行替换为"why"
sed '2cwhy' test.txt

(2)匹配内容位置新增

# 在包含"222"的行前插入"why"
sed '/222/iwhy' test.txt

# 在包含"333"的行后追加"why"
sed '/333/awhy' test.txt

# 多指令组合:在"222"前插、"333"后插(-e支持多指令)
sed -e '/222/iwhy' -e '/333/awhy' test.txt

(3)新增多行内容

通过\n换行符实现多行插入:

# 在"222"行后追加"why"和"123"(分行)
sed '/222/awhy\n123' test.txt

3. 删除(移除指定行)

通过d(删除)指令移除行,支持行号范围内容匹配

# 删除第2-5行
sed '2,5d' test.txt

# 删除第2行和第5行
sed '2d;5d' test.txt

# 删除包含空行(^$表示空行)
sed '/^$/d' test.txt

# 删除注释行(以#开头)
sed '/^#/d' test.txt

4. 修改(替换文本)

通过s(替换)指令实现文本替换,语法:s#原内容#新内容#选项(分隔符可换为/|)。

(1)普通替换

# 将"old"替换为"new"(仅替换每行第一个匹配)
sed 's#old#new#' test.txt

# 全局替换(g选项:替换每行所有匹配)
sed 's#old#new#g' test.txt

# 示例:移除IP地址中的子网掩码(如192.168.0.102/24 → 192.168.0.102)
ip a s wlo1 | sed -n '4p' | sed 's#/.*##g'

(2)后项引用(正则分组替换)

()捕获分组,\1\2等引用分组内容(需-r启用扩展正则),语法:sed 's#(正则)#\n#g'

# 提取 IP 地址(从"inet 192.168.0.102/24..."中取 IP)
# (.*)捕获 IP 部分,\1 引用该部分作为替换结果,& 表示替换的内容
ip a s wlo1 | sed -n '4p' | sed -r 's#^.*inet (.*)/.*#\1#g'

(3)自动备份替换

修改原始文件时,通过-i.bak保留备份:

# 替换"eee"为"fff",同时备份原文件为test02.bak
sed -i.bak 's#eee#fff#g' test02

(4)注意:危险操作

-n(抑制输出)与-i(修改文件)同时使用会清空文件,需避免:

# 错误示例:会清空test02.bak
sed -ni 's#fff#kkk#g' test02.bak

四、扩展用法(实战场景)

1. 批量修改文件名

结合管道和bash执行生成的命令:

# 将所有.bak文件改名为.txt(& 表示匹配的原文件名)
ls *.bak | sed -r 's#(.*)\.bak#mv & \1.txt#g' | bash

2. 过滤有效内容(非空+非注释行)

# 同时删除空行和注释行
sed -r '/^$/d;/^#/d' line.txt

3. 批量添加前缀/后缀

# 每行开头加"HEAD "
sed 's/^/HEAD &/g' line.txt

# 每行结尾加" TAIL"
sed 's/$/ TAIL/g' line.txt

4. 提取本机IP地址

# 从网卡wlo1中提取IPv4地址
ip a s wlo1 | sed -r -n '4s#^.*inet (.*)/.*#\1#gp'

五、注意事项

  1. 默认不修改原文件:无-i时仅输出到终端,需重定向保存(sed ... > new.txt)。
  2. 正则转义:使用基础正则时,(){}?+|需加\转义;-r模式下可直接使用。
  3. 备份重要:使用-i修改文件前,建议用-i.bak备份(修改后可删除.bak)。
  4. 多行处理:sed按行处理,复杂多行逻辑需结合N(合并行)等高级指令。