sed 命令完整使用手册

_

一、简介

1.1 什么是 sed

sed(stream editor)是一个流编辑器,用于对文本进行过滤和转换。它是 Unix/Linux 系统中最古老且最强大的文本处理工具之一。

核心特点:

  • 逐行处理文本

  • 支持正则表达式

  • 非交互式编辑

  • 可以原地修改文件

  • 支持脚本文件

1.2 工作原理

┌─────────────────────────────────────────────────────────────────────┐
│                    sed 工作流程                                     │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│    输入文件/标准输入                                                │
│         │                                                           │
│         ▼                                                           │
│    ┌─────────────┐                                                 │
│    │  读取一行   │                                                 │
│    └──────┬──────┘                                                 │
│           │                                                         │
│           ▼                                                         │
│    ┌─────────────┐    不匹配    ┌─────────────┐                    │
│    │  模式匹配   │ ──────────► │  输出原行   │                    │
│    └──────┬──────┘              └─────────────┘                    │
│           │ 匹配                                                    │
│           ▼                                                         │
│    ┌─────────────┐                                                 │
│    │  执行命令   │                                                 │
│    └──────┬──────┘                                                 │
│           │                                                         │
│           ▼                                                         │
│    ┌─────────────┐                                                 │
│    │  输出结果   │                                                 │
│    └─────────────┘                                                 │
│                                                                     │
│    重复直到文件结束                                                 │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

1.3 sed 模式空间与保持空间

┌─────────────────────────────────────────────────────────────────────┐
│                    sed 的两个缓冲区                                 │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  ┌──────────────────────────────────────────────────────────────┐  │
│  │ 模式空间 (Pattern Space)                                     │  │
│  │ ───────────────────────                                      │  │
│  │ • 当前处理的行                                               │  │
│  │ • 大多数命令在这里操作                                       │  │
│  │ • 每处理完一行,自动清空                                     │  │
│  └──────────────────────────────────────────────────────────────┘  │
│                                                                     │
│  ┌──────────────────────────────────────────────────────────────┐  │
│  │ 保持空间 (Hold Space)                                        │  │
│  │ ─────────────────────                                        │  │
│  │ • 临时存储区                                                 │  │
│  │ • 用于多行处理                                               │  │
│  │ • 需要手动管理                                               │  │
│  └──────────────────────────────────────────────────────────────┘  │
│                                                                     │
│  命令:h/H (复制/追加到保持空间), g/G (获取到模式空间)              │
│        x (交换)                                                    │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

二、安装

2.1 各平台安装

Linux

# Debian/Ubuntu
sudo apt update
sudo apt install sed

# CentOS/RHEL
sudo yum install sed

# Alpine
apk add sed

# Arch Linux
sudo pacman -S sed

macOS

# macOS 自带 sed,但建议安装 GNU sed
brew install gsed

# 创建别名
alias sed='gsed'

Windows

# Coreutils
winget install Microsoft.Coreutils

# Git Bash 自带 sed

# 或通过 Chocolatey
choco install sed

# 或使用 WSL
wsl sed

2.2 验证安装

sed --version
# 输出: sed (GNU sed) 4.8

# 测试运行
echo "hello world" | sed 's/world/sed/'
# 输出: hello sed

2.3 BSD sed vs GNU sed

# BSD sed (macOS 默认)
# -i 需要指定备份后缀(可以是空字符串)
sed -i '' 's/old/new/' file.txt

# GNU sed (Linux 默认)
# -i 不需要指定后缀
sed -i 's/old/new/' file.txt

# 兼容写法
# 创建备份
sed -i.bak 's/old/new/' file.txt

三、基础语法

3.1 命令格式

sed [选项] '命令' [文件]

# 或
sed [选项] -e '命令1' -e '命令2' [文件]

# 或从脚本文件读取
sed [选项] -f 脚本文件 [文件]

3.2 常用选项

选项

说明

示例

-n

静默模式,不自动打印

sed -n 'p'

-e

添加脚本命令

sed -e 's/a/b/' -e 's/c/d/'

-f

从文件读取脚本

sed -f script.sed

-i

原地编辑文件

sed -i 's/old/new/' file

-i.bak

原地编辑并备份

sed -i.bak 's/old/new/' file

-r / -E

使用扩展正则表达式

sed -r 's/a+/b/'

-l

指定行长度

sed -l 80

-s

将文件视为独立流

sed -s '1p' *.txt

-u

无缓冲输出

sed -u 's/a/b/'

-z

使用 NUL 分隔行

sed -z 's/\n/ /g'

3.3 命令格式

[地址1[,地址2]]命令[参数]

# 示例
sed 'p'          # 无地址,作用于所有行
sed '1p'         # 地址为 1,只作用于第 1 行
sed '1,5p'       # 地址为 1-5,作用于第 1-5 行
sed '/pattern/p' # 地址为匹配 pattern 的行

四、基础操作

4.1 替换命令 (s)

基本替换

# 替换每行第一个匹配
echo "hello world world" | sed 's/world/sed/'
# 输出: hello sed world

# 全局替换
echo "hello world world" | sed 's/world/sed/g'
# 输出: hello sed sed

# 替换第 N 个匹配
echo "aaa aaa aaa" | sed 's/aaa/bbb/2'
# 输出: aaa bbb aaa

替换标志

标志

说明

示例

g

全局替换

s/old/new/g

数字

替换第 N 个匹配

s/old/new/2

p

打印替换的行

s/old/new/p

w 文件

写入文件

s/old/new/w out.txt

i

忽略大小写

s/old/new/i

e

执行命令

s/.*/echo &/e

m

多行模式

s/^/>>/gm

分隔符

# 默认使用 /
sed 's/old/new/' file

# 使用其他分隔符(推荐用于处理路径)
sed 's#/old#/new#' file
sed 's|/old|/new|' file
sed 's@/old@/new@' file
sed 's:/old:/new:' file

# 使用 # 分隔符的示例
echo "/usr/local/bin" | sed 's#/usr#/opt#'
# 输出: /opt/local/bin

使用 & 和 \1

# & 代表匹配的整个文本
echo "hello" | sed 's/hello/[&]/'
# 输出: [hello]

echo "hello world" | sed 's/\w\+/[&]/g'
# 输出: [hello] [world]

# \1, \2 代表分组
echo "hello world" | sed 's/\(\w\+\) \(\w\+\)/[\1] [\2]/'
# 输出: [hello] [world]

# 使用扩展正则(推荐)
echo "hello world" | sed -r 's/(\w+) (\w+)/[\1] [\2]/'
# 输出: [hello] [world]

# 交换两个词
echo "hello world" | sed -r 's/(\w+) (\w+)/\2 \1/'
# 输出: world hello

4.2 删除命令 (d)

# 删除第 3 行
sed '3d' file.txt

# 删除第 1-5 行
sed '1,5d' file.txt

# 删除最后一行
sed '$d' file.txt

# 删除空行
sed '/^$/d' file.txt

# 删除匹配行
sed '/pattern/d' file.txt

# 删除不匹配的行
sed '/pattern/!d' file.txt

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

# 删除所有行(仅显示)
seq 5 | sed 'd'
# 无输出

# 删除从匹配行到末尾
sed '/pattern/,$d' file.txt

4.3 打印命令 (p)

# 打印第 3 行(会打印两次)
sed '3p' file.txt

# 只打印第 3 行
sed -n '3p' file.txt

# 打印第 1-5 行
sed -n '1,5p' file.txt

# 打印最后一行
sed -n '$p' file.txt

# 打印匹配行
sed -n '/pattern/p' file.txt

# 打印行号
sed '=' file.txt

# 打印行号和内容
sed '=' file.txt | sed 'N;s/\n/ /'

# 打印奇数行
sed -n '1~2p' file.txt

# 打印偶数行
sed -n '2~2p' file.txt

# 打印从第 N 行开始的所有行
sed -n '5,$p' file.txt

4.4 插入与追加 (i, a)

# 在第 2 行前插入
sed '2i\INSERTED LINE' file.txt

# 在第 2 行后追加
sed '2a\APPENDED LINE' file.txt

# 在文件开头插入
sed '1i\HEADER' file.txt

# 在文件末尾追加
sed '$a\FOOTER' file.txt

# 在匹配行前插入
sed '/pattern/i\BEFORE' file.txt

# 在匹配行后追加
sed '/pattern/a\AFTER' file.txt

# 在每行前插入
sed 'i\> ' file.txt

# 在每行后追加
sed 'a\---' file.txt

# 插入多行
sed '2i\
LINE 1\
LINE 2\
LINE 3' file.txt

4.5 修改命令 (c)

# 替换第 2 行
sed '2c\REPLACED LINE' file.txt

# 替换第 1-3 行
sed '1,3c\REPLACED MULTIPLE LINES' file.txt

# 替换匹配行
sed '/pattern/c\REPLACED' file.txt

# 替换空行
sed '/^$/c\EMPTY' file.txt

4.6 原地编辑 (-i)

# 直接修改文件(危险操作)
sed -i 's/old/new/' file.txt

# 修改前备份
sed -i.bak 's/old/new/' file.txt

# 批量修改
sed -i 's/old/new/' *.txt

# 递归修改
find . -name "*.txt" -exec sed -i 's/old/new/' {} +

# macOS 兼容写法
sed -i '' 's/old/new/' file.txt

五、地址与范围

5.1 行号地址

# 第 N 行
sed '3p' file.txt

# 第 N 到 M 行
sed '3,5p' file.txt

# 最后一行
sed '$p' file.txt

# 从第 N 行到末尾
sed '3,$p' file.txt

# 第 N 行之后的 M 行
sed '3,+2p' file.txt

# 每 N 行
sed '1~3p' file.txt  # 第 1, 4, 7, 10... 行

5.2 正则地址

# 匹配 pattern 的行
sed '/pattern/p' file.txt

# 从匹配 start 到匹配 end
sed '/start/,/end/p' file.txt

# 从第 N 行到匹配 pattern
sed '3,/pattern/p' file.txt

# 从匹配 pattern 到末尾
sed '/pattern/,$p' file.txt

# 匹配多个模式
sed '/pattern1/p; /pattern2/p' file.txt

5.3 地址取反 (!)

# 删除不匹配的行
sed '/pattern/!d' file.txt

# 修改不匹配的行
sed '/pattern/!s/^/# /' file.txt

# 打印不匹配的行
sed -n '/pattern/!p' file.txt

# 删除除第 3-5 行外的所有行
sed '3,5!d' file.txt

5.4 地址组合

# 多个地址范围
sed -e '1,5s/old/new/' -e '10,15s/foo/bar/' file.txt

# 嵌套地址
sed '/start/,/end/{/pattern/p}' file.txt

# 条件执行多个命令
sed '/pattern/{s/old/new/; s/foo/bar/}' file.txt

六、命令详解

6.1 替换命令 (s///)

# 语法
s/模式/替换/[标志]

# 基本替换
sed 's/hello/world/' file.txt

# 使用不同的分隔符
sed 's|/usr/local|/opt|' file.txt
sed 's#/usr/local#/opt#' file.txt

# 忽略大小写
sed 's/hello/WORLD/i' file.txt

# 多次替换
sed 's/a/A/g; s/b/B/g' file.txt

# 条件替换
sed '/pattern/s/old/new/' file.txt

# 分组替换
sed -r 's/([a-z]+) ([0-9]+)/\2 \1/' file.txt

# 大小写转换
# \u 首字母大写
echo "hello" | sed 's/\w\+/\u&/'
# 输出: Hello

# \U 全部大写
echo "hello" | sed 's/\w\+/\U&/'
# 输出: HELLO

# \l 首字母小写
echo "HELLO" | sed 's/\w\+/\l&/'
# 输出: hELLO

# \L 全部小写
echo "HELLO" | sed 's/\w\+/\L&/'
# 输出: hello

# \E 结束大小写转换
echo "hello WORLD" | sed 's/\w\+/\u&\E/g'
# 输出: Hello World

6.2 删除命令 (d)

# 删除指定行
sed '5d' file.txt

# 删除范围行
sed '3,7d' file.txt

# 删除空行
sed '/^$/d' file.txt

# 删除空白行(包含空格)
sed '/^[[:space:]]*$/d' file.txt

# 删除注释行
sed '/^#/d' file.txt

# 删除匹配行
sed '/error/d' file.txt

# 保留匹配行(删除不匹配的)
sed '/success/!d' file.txt

# 删除连续空行(只保留一个)
sed '/./,/^$/!d' file.txt

# 删除第 N 行到匹配行
sed '3,/pattern/d' file.txt

6.3 打印命令 (p)

# 打印行
sed -n '3p' file.txt

# 打印范围
sed -n '3,5p' file.txt

# 打印匹配行
sed -n '/pattern/p' file.txt

# 打印并显示行号
sed -n '/pattern/{=;p}' file.txt

# 打印前 N 行
sed -n '1,5p' file.txt

# 打印最后 N 行
sed -n '$p' file.txt

# 打印奇偶行
sed -n '1~2p' file.txt  # 奇数行
sed -n '2~2p' file.txt  # 偶数行

6.4 插入/追加 (i/a)

# 插入 (i) - 在行前
sed '3i\INSERTED' file.txt

# 追加 (a) - 在行后
sed '3a\APPENDED' file.txt

# 在匹配行前后添加
sed '/pattern/i\BEFORE' file.txt
sed '/pattern/a\AFTER' file.txt

# 添加多行
sed '3a\
LINE 1\
LINE 2' file.txt

# 在行首添加
sed 's/^/PREFIX /' file.txt

# 在行尾添加
sed 's/$/ SUFFIX/' file.txt

6.5 修改命令 (c)

# 替换整行
sed '3c\NEW LINE' file.txt

# 替换范围
sed '3,5c\REPLACED' file.txt

# 替换匹配行
sed '/pattern/c\REPLACED' file.txt

6.6 读写命令 (r/w)

# 读取文件并插入
sed '/pattern/r insert.txt' file.txt

# 在指定行后插入文件
sed '3r insert.txt' file.txt

# 写入到文件
sed -n '/pattern/w output.txt' file.txt

# 写入指定行
sed -n '3,5w output.txt' file.txt

# 分割文件
sed -n '/pattern1/w file1.txt; /pattern2/w file2.txt' file.txt

6.7 多行命令 (N/D/P)

# N - 读取下一行到模式空间
sed 'N' file.txt  # 合并相邻两行

# 合并所有行
sed ':a;N;$!ba;s/\n/ /g' file.txt

# D - 删除模式空间第一行
sed 'N;D' file.txt

# P - 打印模式空间第一行
sed -n 'N;P' file.txt

# 处理跨行匹配
sed 'N;s/pattern1\npattern2/replacement/' file.txt

# 删除空行并合并
sed '/^$/N;/^\n$/D' file.txt

6.8 保持空间命令 (h/H/g/G/x)

# h - 复制模式空间到保持空间
# H - 追加模式空间到保持空间
# g - 复制保持空间到模式空间
# G - 追加保持空间到模式空间
# x - 交换模式空间和保持空间

# 反转文件行
sed -n '1!G;h;$p' file.txt

# 反转文件(更简洁)
tac file.txt  # 或 sed '1!G;h;$!d' file.txt

# 合并相邻行
sed 'N;s/\n/ /' file.txt

# 交换行(交换第 2 和第 3 行)
sed '2{h;d};3{G}' file.txt

# 复制行
sed '/pattern/{h};/pattern2/{G}' file.txt

# 累积匹配行
sed '/pattern/H;$!d;g' file.txt

6.9 分支与测试 (b/t/😃

# :label - 定义标签
# b label - 跳转到标签
# t label - 如果替换成功则跳转
# T label - 如果替换失败则跳转

# 删除所有行的前导空格
sed ':a;s/^\( *\)\( *\)/\1/;ta' file.txt

# 循环替换直到没有变化
sed ':a;s/  */ /g;ta' file.txt

# 条件跳转
sed '/pattern/b end; s/old/new/; :end' file.txt

# 删除嵌套括号内容
sed ':a;s/([^()]*)//g;ta' file.txt

# 计算行数
sed -n '$=' file.txt

6.10 其他命令

# = - 打印行号
sed '=' file.txt

# l - 打印不可见字符
sed -n 'l' file.txt

# q - 退出
sed '5q' file.txt  # 只处理前 5 行

# Q - 静默退出
sed '/pattern/Q' file.txt

# # - 注释
sed '# This is a comment' file.txt

# {} - 命令分组
sed '/pattern/{s/old/new/;p}' file.txt

# y - 字符转换(类似 tr)
sed 'y/abc/ABC/' file.txt

# v - 版本检查
sed --version

七、正则表达式

7.1 基本正则 (BRE)

# 基本字符
.      # 任意单个字符
*      # 前一个字符出现 0 次或多次
^      # 行首
$      # 行尾
[list] # 字符列表
[^]    # 不在列表中的字符
\n     # 换行符
\      # 转义字符

# 示例
sed 's/a.c/XYZ/' file.txt      # abc, a1c, a_c 等都会被匹配
sed 's/ab*c/XYZ/' file.txt     # ac, abc, abbc 等都会被匹配
sed 's/^start/START/' file.txt # 只匹配行首的 start
sed 's/end$/END/' file.txt     # 只匹配行尾的 end
sed 's/[abc]/X/' file.txt      # 匹配 a, b, c 中的任意一个
sed 's/[^abc]/X/' file.txt     # 匹配不是 a, b, c 的字符

7.2 扩展正则 (ERE)

# 使用 -r 或 -E 选项
sed -r 's/pattern/replacement/' file.txt

# 扩展字符
+      # 前一个字符出现 1 次或多次
?      # 前一个字符出现 0 次或 1 次
{n}    # 前一个字符出现 n 次
{n,}   # 前一个字符出现至少 n 次
{n,m}  # 前一个字符出现 n 到 m 次
|      # 或
()     # 分组

# 示例
sed -r 's/ab+c/XYZ/' file.txt     # abc, abbc, abbbc 等
sed -r 's/ab?c/XYZ/' file.txt     # ac, abc
sed -r 's/a{3}/AAA/' file.txt     # aaa 被替换为 AAA
sed -r 's/a{2,4}/AA/' file.txt    # aa, aaa, aaaa 被替换为 AA
sed -r 's/cat|dog/pet/' file.txt  # cat 或 dog 被替换为 pet
sed -r 's/(ab)+/X/' file.txt      # ab, abab, ababab 等

7.3 字符类

# POSIX 字符类
[:alnum:]   # 字母和数字
[:alpha:]   # 字母
[:blank:]   # 空格和制表符
[:cntrl:]   # 控制字符
[:digit:]   # 数字
[:graph:]   # 可打印字符(不包括空格)
[:lower:]   # 小写字母
[:print:]   # 可打印字符
[:punct:]   # 标点符号
[:space:]   # 空白字符
[:upper:]   # 大写字母
[:xdigit:]  # 十六进制数字

# 示例
sed 's/[[:digit:]]/X/g' file.txt      # 替换所有数字
sed 's/[[:space:]]+/,/g' file.txt     # 替换连续空格为逗号
sed 's/[[:upper:]]/\L&/g' file.txt    # 转换为小写
sed 's/[[:punct:]]//g' file.txt       # 删除标点符号

7.4 正则示例

# 匹配邮箱
sed -r 's/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/EMAIL/g' file.txt

# 匹配 URL
sed -r 's|https?://[^[:space:]]+|URL|g' file.txt

# 匹配 IP 地址
sed -r 's/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/IP/g' file.txt

# 匹配日期 (YYYY-MM-DD)
sed -r 's/[0-9]{4}-[0-9]{2}-[0-9]{2}/DATE/g' file.txt

# 匹配电话号码
sed -r 's/[0-9]{3}-[0-9]{4}-[0-9]{4}/PHONE/g' file.txt

# 匹配 HTML 标签
sed -r 's/<[^>]+>//g' file.html

# 匹配重复单词
sed -r 's/\b(\w+)\s+\1\b/\1/g' file.txt

# 删除前后空格
sed 's/^[[:space:]]*//;s/[[:space:]]*$//' file.txt

八、高级用法

8.1 多命令执行

# 使用 -e 选项
sed -e 's/a/A/' -e 's/b/B/' file.txt

# 使用分号
sed 's/a/A/; s/b/B/' file.txt

# 使用 { } 分组
sed '/pattern/{s/a/A/;s/b/B/}' file.txt

# 使用换行(在脚本中更清晰)
sed '
s/a/A/
s/b/B/
s/c/C/
' file.txt

8.2 脚本文件

# 创建 sed 脚本文件 script.sed
#!/usr/bin/sed -f

# 删除空行
/^$/d

# 删除注释
/^#/d

# 替换
s/old/new/g

# 使用脚本
sed -f script.sed file.txt

# 直接执行脚本
chmod +x script.sed
./script.sed file.txt

8.3 模式空间与保持空间

# 模式空间 - 当前处理的行
# 保持空间 - 临时存储

# h - 复制模式空间到保持空间(覆盖)
# H - 追加模式空间到保持空间
# g - 复制保持空间到模式空间(覆盖)
# G - 追加保持空间到模式空间
# x - 交换两个空间

# 示例:反转行顺序
seq 5 | sed -n '1!G;h;$p'
# 输出:
# 5
# 4
# 3
# 2
# 1

# 示例:合并每两行
sed 'N;s/\n/ /' file.txt

# 示例:复制匹配行到文件末尾
sed -n '/pattern/H;$p' file.txt

# 示例:累积内容
sed '/pattern/!d;H;$!d;g' file.txt

8.4 分支与循环

# :label - 定义标签
# b label - 无条件跳转
# t label - 替换成功则跳转
# T label - 替换失败则跳转

# 示例:循环删除多余的空格
sed ':a;s/  / /;ta' file.txt

# 示例:循环添加前缀
echo "abc" | sed ':a;s/^/>>/;ta'
# 无限循环!不要这样做

# 示例:有条件的循环
sed ':a;s/abc/X/;ta' file.txt  # 替换所有的 abc 为 X

# 示例:跳过某些行
sed '/pattern/b skip; s/old/new/; :skip' file.txt

# 示例:删除嵌套括号
sed ':a;s/([^()]*)//g;ta' file.txt

8.5 多行处理

# N - 读取下一行到模式空间
# D - 删除模式空间第一行
# P - 打印模式空间第一行

# 示例:合并相邻行
sed 'N;s/\n/ /' file.txt

# 示例:合并所有行
sed ':a;N;$!ba;s/\n/ /g' file.txt

# 示例:删除空行(保留一个)
sed '/^$/N;/^\n$/D' file.txt

# 示例:跨行替换
sed 'N;s/pattern1\npattern2/replacement/' file.txt

# 示例:格式化段落
sed '/./{H;$!d};x;s/\n\n*/\n\n/g' file.txt

# 示例:删除 HTML 标签(多行)
sed ':a;N;$!ba;s/<[^>]*>//g' file.html

8.6 条件执行

# {} 分组命令
sed '/pattern/{s/a/A/;s/b/B/;p}' file.txt

# 多条件
sed '/pattern1/{
  s/a/A/
  /pattern2/d
}' file.txt

# 嵌套条件
sed '/start/,/end/{
  /pattern1/s/old/new/
  /pattern2/d
}' file.txt

# 使用 ! 取反
sed '/pattern/!s/old/new/' file.txt

# 条件退出
sed '/pattern/q' file.txt

# 条件写入
sed -n '/pattern/w output.txt' file.txt

8.7 高级替换技巧

# 大小写转换
# \u - 首字母大写
# \U - 全部大写
# \l - 首字母小写
# \L - 全部小写
# \E - 结束转换

echo "hello world" | sed 's/\w\+/\u&/g'
# 输出: Hello World

echo "hello world" | sed 's/.*/\U&/'
# 输出: HELLO WORLD

# 驼峰转换
echo "hello_world_test" | sed -r 's/(_|^)([a-z])/\U\2/g'
# 输出: HelloWorldTest

# 蛇形转换
echo "HelloWorldTest" | sed -r 's/([A-Z])/_\L\1/g;s/^_//'
# 输出: hello_world_test

# 每行添加行号
sed '=' file.txt | sed 'N;s/\n/\t/'

# 添加序号
sed = file.txt | sed 'N;s/^/   /;s/\n/\t/'

九、实战示例

9.1 文本清理

删除空白行

# 删除完全空白的行
sed '/^$/d' file.txt

# 删除只含空格/制表符的行
sed '/^[[:space:]]*$/d' file.txt

# 删除连续空行(保留一个)
sed '/./,/^$/!d' file.txt

# 删除开头的空行
sed '/./,$!d' file.txt

# 删除结尾的空行
sed -e :a -e '/^\n*$/{$d;N;};$!ba' file.txt

删除注释

# 删除 # 开头的注释
sed '/^#/d' file.txt

# 删除行内注释(保留内容)
sed 's/#.*//' file.txt

# 删除 // 注释(C 风格)
sed 's|//.*||' file.txt

# 删除 /* */ 注释(简单)
sed 's|/\*.*\*/||' file.txt

# 删除多行注释
sed ':a;s|/\*[^*]*\*\+\([^/*][^*]*\*\+\)*/||;ta' file.txt

去除空格

# 删除行首空格
sed 's/^[[:space:]]*//' file.txt

# 删除行尾空格
sed 's/[[:space:]]*$//' file.txt

# 删除首尾空格
sed 's/^[[:space:]]*//;s/[[:space:]]*$//' file.txt

# 压缩多个空格为一个
sed 's/[[:space:]]\+/ /g' file.txt

# 删除所有空格
sed 's/[[:space:]]//g' file.txt

9.2 文本转换

大小写转换

# 首字母大写
sed 's/\b\(.\)/\u\1/' file.txt

# 每个单词首字母大写
sed -r 's/\b([a-z])/\u\1/g' file.txt

# 全部大写
sed 's/.*/\U&/' file.txt

# 全部小写
sed 's/.*/\L&/' file.txt

# 句首大写
sed 's/^\(.\)/\u\1/' file.txt

格式转换

# CSV 转表格
sed 's/,/\t/g' file.csv

# 制表符转空格
sed 's/\t/  /g' file.txt

# 空格转制表符
sed 's/  /\t/g' file.txt

# 添加引号
sed 's/[^,]*/"&"/g' file.csv

# 转换为 HTML 段落
sed 's/.*$/<p>&<\/p>/' file.txt

# 添加 HTML 转义
sed 's/&/\&amp;/g;s/</\&lt;/g;s/>/\&gt;/g' file.txt

编码转换

# URL 编码(简单版)
sed 's/%/%25/g;s/ /%20/g;s/\//%2F/g' file.txt

# HTML 实体解码(简单版)
sed 's/&lt;/</g;s/&gt;/>/g;s/&amp;/\&/g' file.txt

# Base64 编码(需要配合)
sed 's/.*/echo & | base64/e' file.txt

9.3 日志处理

Apache 日志

# 提取 IP 地址
sed -n 's/^\([0-9.]*\).*/\1/p' access.log

# 提取特定状态码
sed -n '/" 404 /p' access.log

# 提取特定日期的日志
sed -n '/\[02\/Jan\/2024/p' access.log

# 统计 URL
sed -n 's/.*"\([A-Z]*\) \([^ ]*\) .*/\2/p' access.log | sort | uniq -c

Nginx 日志

# 提取响应时间
sed -n 's/.* \([0-9.]*\)$/\1/p' access.log

# 找出慢请求(>1s)
sed -n '/ [1-9][0-9]*\.[0-9]*$/p' access.log

# 提取 User-Agent
sed -n 's/.*"\([^"]*\)"$/\1/p' access.log

应用日志

# 提取错误日志
sed -n '/ERROR/p' app.log

# 提取特定时间范围
sed -n '/2024-01-01 10:00/,/2024-01-01 11:00/p' app.log

# 提取异常堆栈(多行)
sed -n '/Exception/,/^[[:space:]]*$/p' app.log

# 统计日志级别
sed -n 's/.*\(ERROR\|WARN\|INFO\|DEBUG\).*/\1/p' app.log | sort | uniq -c

9.4 配置文件处理

修改配置

# 修改配置值
sed -i 's/max_connections=.*/max_connections=100/' config.ini

# 注释掉配置
sed -i 's/^option=/#option=/' config.ini

# 取消注释
sed -i 's/^#option=/option=/' config.ini

# 添加配置(如果不存在)
grep -q "new_option" config.ini || sed -i '$a new_option=value' config.ini

# 替换端口
sed -i 's/port=.*/port=8080/' config.ini

INI 文件

# 提取节
sed -n '/\[section\]/,/^\[/p' config.ini

# 提取键值
sed -n 's/^key=\(.*\)/\1/p' config.ini

# 添加新节
sed -i '/^\[/a [new_section]' config.ini

# 删除节
sed -i '/\[section\]/,/^\[/{/^\[/!d}' config.ini

JSON 文件(简单处理)

# 修改 JSON 值(简单版)
sed -i 's/"key":.*/"key": "new_value",/' config.json

# 提取值(简单版)
sed -n 's/.*"key": *"\([^"]*\)".*/\1/p' config.json

# 格式化 JSON(需要配合)
# 注意:复杂 JSON 处理建议使用 jq

9.5 代码处理

批量重命名变量

# 重命名变量
sed -i 's/oldName/newName/g' *.js

# 重命名函数
sed -i 's/function oldFunc/function newFunc/g' *.js

# 重命名类
sed -i 's/class OldClass/class NewClass/g' *.php

代码清理

# 删除调试语句
sed -i '/console\.log/d' *.js
sed -i '/print(/d' *.py
sed -i '/System\.out\.println/d' *.java

# 删除 TODO 注释
sed -i '/\/\/ TODO/d' *.js

# 删除空行
sed -i '/^$/d' *.py

代码格式化

# 删除行尾空格
sed -i 's/[[:space:]]*$//' *.py

# 统一缩进(空格转制表符)
sed -i 's/    /\t/g' *.py

# 添加分号(如果缺失)
sed -i 's/\([^;]\)$/\1;/' *.js

9.6 数据提取

提取字段

# 提取第一列
sed 's/^\([^,]*\),.*/\1/' file.csv

# 提取第 N 列(以逗号分隔)
sed 's/^[^,]*,\([^,]*\),.*/\1/' file.csv  # 第 2 列

# 提取最后一列
sed 's/.*,\([^,]*\)$/\1/' file.csv

# 提取特定格式
sed -n 's/.*id=\([0-9]*\).*/\1/p' file.txt

提取匹配内容

# 提取邮箱
sed -n 's/.*\([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]\{2,\}\).*/\1/p' file.txt

# 提取 URL
sed -n 's/.*\(https\?:\/\/[^ ]*\).*/\1/p' file.txt

# 提取 IP 地址
sed -n 's/.*\([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\).*/\1/p' file.txt

# 提取日期
sed -n 's/.*\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\).*/\1/p' file.txt

9.7 文本分析

统计

# 统计行数
sed -n '$=' file.txt

# 统计单词数
sed 's/[^[:space:]]//g' file.txt | wc -c

# 统计字符数
sed 's/\n//g' file.txt | wc -c

# 统计某个词出现次数
sed -n 's/word/word/gp' file.txt | wc -l

查找

# 查找包含 pattern 的行
sed -n '/pattern/p' file.txt

# 查找不包含 pattern 的行
sed -n '/pattern/!p' file.txt

# 查找并显示行号
sed -n '/pattern/{=;p}' file.txt

# 查找上下文
sed -n '/pattern/{N;P}' file.txt  # 下一行

十、技巧与最佳实践

10.1 调试技巧

# 显示详细信息
sed --version

# 测试命令(不修改文件)
sed 's/old/new/' file.txt

# 使用 -n 调试
sed -n 's/old/new/p' file.txt

# 打印模式空间
sed -n 'l' file.txt

# 分步执行
sed 's/a/A/' file.txt | sed 's/b/B/'

# 使用 echo 测试
echo "test string" | sed 's/test/TEST/'

10.2 性能优化

# 使用地址范围限制
sed '1,100s/old/new/' large.txt  # 只处理前 100 行

# 合并多个命令
sed 's/a/A/; s/b/B/; s/c/C/' file.txt  # 优于三次调用

# 提前退出
sed '/pattern/q' file.txt  # 找到后立即退出

# 使用 -s 处理多个小文件
sed -s '1p' *.txt

# 避免不必要的替换
sed '/pattern/s/old/new/' file.txt  # 只在匹配行替换

10.3 安全实践

# 始终备份
sed -i.bak 's/old/new/' file.txt

# 先测试
sed 's/old/new/' file.txt > /dev/null && sed -i 's/old/new/' file.txt

# 使用版本控制
git commit -am "Before sed changes"
sed -i 's/old/new/' *.txt
git diff

# 限制范围
sed '1,10s/old/new/' file.txt  # 只处理前 10 行

# 检查结果
sed -i 's/old/new/' file.txt
grep "new" file.txt | head

10.4 常用脚本

# 删除 CRLF(Windows 换行)
sed 's/\r$//' file.txt

# 添加 CRLF
sed 's/$/\r/' file.txt

# 删除 BOM
sed '1s/^\xEF\xBB\xBF//' file.txt

# 删除 ANSI 颜色代码
sed 's/\x1b\[[0-9;]*m//g' file.txt

# 去除 HTML 标签
sed 's/<[^>]*>//g' file.html

# 合并多行为一行
sed ':a;N;$!ba;s/\n/ /g' file.txt

# 分割每行到多行
sed 's/.\{80\}/&\n/g' file.txt

# 添加行号
sed = file.txt | sed 'N;s/\n/\t/'

# 反转行
sed -n '1!G;h;$p' file.txt

10.5 常见陷阱

陷阱 1:忘记引号

# 错误
sed s/old/new/ file.txt  # 特殊字符会出问题

# 正确
sed 's/old/new/' file.txt

陷阱 2:分隔符冲突

# 错误(路径中的 / 会冲突)
sed 's//usr/local//opt/' file.txt

# 正确(使用其他分隔符)
sed 's|/usr/local|/opt|' file.txt

陷阱 3:贪婪匹配

# 贪婪匹配(匹配到最后一个)
echo "<a><b>text</b></a>" | sed 's/<.*>//'
# 输出: text</b></a>(错误)

# 非贪婪匹配(使用 [^>])
echo "<a><b>text</b></a>" | sed 's/<[^>]*>//g'
# 输出: text(正确)

陷阱 4:macOS sed

# Linux
sed -i 's/old/new/' file.txt

# macOS(需要指定备份后缀)
sed -i '' 's/old/new/' file.txt

# 兼容写法(创建备份)
sed -i.bak 's/old/new/' file.txt

陷阱 5:多行处理

# 错误:sed 默认不处理跨行
sed 's/line1\nline2/replaced/' file.txt  # 不会工作

# 正确:使用 N 读取多行
sed 'N;s/line1\nline2/replaced/' file.txt

十一、sed vs 其他工具

11.1 sed vs awk

# sed:简单的文本替换
sed 's/old/new/' file.txt

# awk:复杂的数据处理
awk '{gsub(/old/, "new"); print}' file.txt

# sed 适合:
# - 简单替换
# - 删除行
# - 行编辑

# awk 适合:
# - 按列处理
# - 复杂计算
# - 格式化输出

11.2 sed vs grep

# grep:查找匹配行
grep "pattern" file.txt

# sed:查找并修改
sed '/pattern/s/old/new/' file.txt

# grep 适合:查找
# sed 适合:替换和编辑

11.3 sed vs tr

# tr:字符转换
tr 'a-z' 'A-Z' < file.txt

# sed:更灵活的转换
sed 's/[a-z]/\U&/g' file.txt

# tr 适合:单字符转换
# sed 适合:模式匹配和替换

11.4 sed vs perl

# sed:简单替换
sed 's/old/new/g' file.txt

# perl:更强大的正则
perl -pe 's/old/new/g' file.txt

# sed 适合:简单任务
# perl 适合:复杂正则和处理

11.5 选择建议

任务

推荐工具

简单替换

sed

删除/插入行

sed

按列处理

awk

查找匹配

grep

JSON 处理

jq

复杂正则

perl

交互编辑

vim


附录

A. 命令速查表

地址

地址

说明

示例

N

第 N 行

3p

N,M

第 N 到 M 行

3,5p

$

最后一行

$p

/pattern/

匹配 pattern 的行

/error/p

/p1/,/p2/

从匹配 p1 到 p2

/start/,/end/p

N~M

从 N 开始每 M 行

1~2p

!

取反

/pattern/!d

命令

命令

说明

示例

s

替换

s/old/new/

d

删除

3d

p

打印

-n '3p'

i

行前插入

3i\text

a

行后追加

3a\text

c

替换整行

3c\text

r

读取文件

3r file

w

写入文件

3w file

y

字符转换

y/abc/ABC/

=

打印行号

3=

q

退出

5q

N

读取下一行

N

D

删除首行

D

P

打印首行

P

h

复制到保持空间

h

g

从保持空间获取

g

x

交换

x

:label

定义标签

:a

b label

跳转

ba

t label

成功跳转

ta

替换标志

标志

说明

示例

g

全局替换

s/a/b/g

N

替换第 N 个

s/a/b/2

p

打印替换的行

s/a/b/p

w file

写入文件

s/a/b/w out

i

忽略大小写

s/a/b/i

e

执行命令

s/.*/echo &/e

正则

元字符

说明

示例

.

任意字符

a.c

*

0 次或多次

ab*c

+

1 次或多次

ab+c

?

0 次或 1 次

ab?c

^

行首

^start

$

行尾

end$

[abc]

字符集

[a-z]

[^abc]

不在字符集

[^0-9]

\{n\}

出现 n 次

a\{3\}

\{n,m\}

出现 n-m 次

a\{2,4\}

\(...\)

分组

\(ab\)*

\1

引用分组

s/\(a\)/\1\1/

&

匹配文本

s/abc/[&]/

B. 常用脚本

文本清理

# 删除空行
sed '/^$/d' file.txt

# 删除行首行尾空格
sed 's/^[[:space:]]*//;s/[[:space:]]*$//' file.txt

# 压缩多个空格
sed 's/[[:space:]]\+/ /g' file.txt

# 删除 CRLF
sed 's/\r$//' file.txt

格式转换

# 添加行号
sed = file.txt | sed 'N;s/\n/\t/'

# 添加前缀
sed 's/^/PREFIX /' file.txt

# 添加后缀
sed 's/$/ SUFFIX/' file.txt

# 反转行
sed -n '1!G;h;$p' file.txt

数据提取

# 提取邮箱
sed -n 's/.*\([a-zA-Z0-9._%+-]\+@[a-zA-Z0-9.-]\+\.[a-zA-Z]\{2,\}\).*/\1/p' file.txt

# 提取 URL
sed -n 's/.*\(https\?:\/\/[^ ]*\).*/\1/p' file.txt

# 提取 IP
sed -n 's/.*\([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\).*/\1/p' file.txt

awk 命令完整使用手册 2026-10-25

评论区