sed 文本处理工具完整指南
sed 学习笔记 -- 流编辑器完全掌握
一、sed 概述与基本概念
1.1 什么是 sed
sed(Stream Editor,流编辑器)是一个强大的非交互式文本处理工具,由贝尔实验室的 Lee E. McMahon 在 1973 年至 1974 年间开发。它从输入流(文件或管道)中读取文本,按照用户指定的编辑命令对文本进行逐行处理,并将结果输出到标准输出。
sed 的核心设计思想
sed 的设计遵循 Unix 哲学——"做一件事,并把它做好"。它专门用于对文本流执行编辑操作,不需要打开交互式编辑器,也不消耗大量内存。sed 一次只处理一行文本,将其读入模式空间(pattern space),执行编辑命令,然后输出结果,接着读取下一行继续处理。
1.2 sed 的工作原理
sed 的工作流程可以概括为三个循环步骤:
读取一行
→
模式空间
→
执行命令
→
输出结果
→
读取下一行
具体来说:
- 读取(Read):sed 从输入文件或标准输入中读取一行文本,将其放入模式空间(pattern space)。模式空间是一个内部缓冲区,用于存储当前正在处理的行。
- 执行(Execute):sed 依次执行用户指定的编辑命令。如果某条命令匹配了当前行的地址条件,则执行相应的操作(如替换、删除、打印等)。
- 输出(Output):默认情况下,sed 会在处理完成后将模式空间的内容输出到标准输出(除非使用了 -n 选项抑制自动输出)。然后清空模式空间,读取下一行,继续循环。
模式空间 vs 保持空间:
sed 有两个内部缓冲区:模式空间(pattern space)是主工作区,每次处理一行;保持空间(hold space)是一个辅助缓冲区,可以暂存数据,用于跨行操作。初学者先掌握模式空间即可,保持空间在多行处理中发挥作用。
1.3 sed 与 awk、grep 的对比
| 工具 | 定位 | 输入 | 输出 | 典型用途 |
| grep | 文本搜索器 | 文件/标准输入 | 匹配的行 | 搜索过滤文本 |
| sed | 流编辑器 | 文件/标准输入 | 编辑后的文本 | 文本替换、删除、插入 |
| awk | 文本分析器 | 结构化文本 | 格式化的报告 | 字段提取、数据统计 |
何时选择 sed?
- 需要在脚本中执行简单的文本替换(如配置文件修改)
- 需要批量删除或插入特定行
- 需要在不打开编辑器的情况下处理大文件
- 管道流水线中的一个环节(如过滤和转换输出)
二、安装与基本使用
2.1 sed 的版本与安装
sed 有多个实现版本,最常用的是 GNU sed(Linux 系统默认)和 BSD sed(macOS 系统默认)。两者在功能上基本一致,但部分选项和正则表达式的行为存在细微差异。
| 操作系统 | 默认 sed | 检查命令 | 安装/更新 |
| Linux (Ubuntu/Debian) | GNU sed | sed --version | apt install sed |
| Linux (CentOS/RHEL) | GNU sed | sed --version | yum install sed |
| macOS | BSD sed | sed --version(可能报错) | brew install gnu-sed |
| Windows (WSL) | GNU sed | sed --version | 随 WSL 发行版预装 |
| Windows (Git Bash) | GNU sed | sed --version | 随 Git for Windows 安装 |
GNU sed 与 BSD sed 的重要区别
- -i 选项:GNU sed 的
sed -i 's/old/new/g' file 可以直接修改文件;BSD sed 需要 sed -i '' 's/old/new/g' file(-i 后必须跟一个备份扩展名参数,空字符串表示不备份)。
- -E 选项:GNU sed 支持
-r(兼容)和 -E(推荐)启用扩展正则;BSD sed 只支持 -E。
- \c 转义:GNU sed 支持
\c 等更多转义序列。
2.2 基本语法
sed 的基本命令格式如下:
sed [选项] '命令' 文件名
sed [选项] '地址范围命令' 文件名
sed [选项] -f 脚本文件 文件名
-n
-e 命令
-f 脚本文件
-i[后缀]
-E
-r
2.3 第一个 sed 命令
echo -e "hello world\nnice to meet you\nhello sed" > test.txt
cat test.txt
sed '' test.txt
sed -n '/hello/p' test.txt
sed 's/hello/hi/' test.txt
sed '/nice/d' test.txt
2.4 命令行中使用单引号与双引号
sed 's/$HOME/\/home/' file.txt
home="/home/user"
sed "s|OLD_HOME|$home|" file.txt
sed "s/\\$HOME/\/home/" file.txt
prefix="user"
sed 's/^/'$prefix'/' file.txt
sed 's/^/'"$prefix"'/' file.txt
引号使用建议
始终优先使用单引号包裹 sed 命令。如果需要在 sed 命令中嵌入 Shell 变量,先关闭单引号,用双引号包裹变量,再重新打开单引号。这样可以避免 Shell 对 sed 命令中的特殊字符进行不必要的解释。
三、基本操作(增删改查)
3.1 打印(p 命令)
p 命令用于打印模式空间的内容。通常与 -n 选项一起使用,避免每一行都被打印两次。
sed -n '2p' file.txt
sed -n '2,5p' file.txt
sed -n '/error/p' log.txt
sed -n '2,+3p' file.txt
sed -n '1~2p' file.txt
sed -n '2~2p' file.txt
sed -n '$p' file.txt
sed -n '3,$p' file.txt
3.2 删除(d 命令)
d 命令删除模式空间的内容,并立即读取下一行开始新的循环(不会执行剩余的 sed 命令)。
sed '2d' file.txt
sed '2,5d' file.txt
sed '/^$/d' file.txt
sed '/debug/d' file.txt
sed '/^#/d' config.ini
sed '3,$d' file.txt
sed '1,$d' file.txt
sed '/^[[:space:]]*$/d' file.txt
sed 's/<[^>]*>//g' file.html
3.3 替换(s 命令)
s 命令是 sed 中最常用的命令,用于在行内进行字符串替换。由于替换操作的复杂性和灵活性,第五章会详细展开,这里先介绍基本用法。
sed 's/old/new/' file.txt
sed 's/old/new/g' file.txt
sed 's/old/new/2' file.txt
sed '3,10s/old/new/g' file.txt
sed -n 's/old/new/p' file.txt
sed 's/^#.*$//' config.ini
3.4 插入(i 命令)和追加(a 命令)
i 命令在匹配行的前面插入文本,a 命令在匹配行的后面追加文本。
sed '3i\这是新插入的行' file.txt
sed '3a\这是新追加的行' file.txt
sed '/header/i\' file.html
sed '$a\# 这是文件末尾追加的内容' file.txt
sed '/main/a\行1\
行2\
行3' file.txt
sed 'G' file.txt
3.5 修改(c 命令)
c 命令将匹配的行替换为指定的文本。
sed '3c\这是替换后的内容' file.txt
sed '/TODO/c\' file.txt
sed '2,4c\被替换的 2-4 行' file.txt
3.6 读取(r 命令)和写入(w 命令)
sed '3r insert.txt' file.txt
sed '$r footer.html' file.html
sed -n '/ERROR/w errors.txt' log.txt
sed -n '10,20w excerpt.txt' file.txt
3.7 退出(q 命令)
sed '10q' large_file.txt
sed '/ERROR/q' log.txt
sed '/ERROR/{s/.*/找到第一个 ERROR,退出/;q}' log.txt
q 命令的效率优势:
使用 sed '10q' 读取大文件的前 10 行比 head -10 在某些场景下更快,因为 sed 在读取到第 10 行后会立即退出,不再继续读取文件的其他部分。这对于处理 GB 级别的大文件非常有用。
3.8 组合操作示例
sed -n '/private/d;p' file.txt
sed -e 's/foo/bar/g' -e 's/abc/xyz/g' file.txt
sed 's/foo/bar/g; s/abc/xyz/g' file.txt
sed '/^$/d; s/old/new/g' file.txt
sed -n '/ERROR/{s/^/!!! /;p}' file.txt
四、正则表达式与模式匹配
4.1 sed 中的正则表达式类型
sed 支持两种类型的正则表达式:基本正则表达式(BRE)是默认使用的;扩展正则表达式(ERE)需要通过 -E 选项启用。
| 元字符 | BRE(基本正则) | ERE(扩展正则,-E) |
+(1次或多次) | \+ 或 \{1,\} | + |
?(0次或1次) | \? 或 \{0,1\} | ? |
{n,m}(区间量词) | \{n,m\} | {n,m} |
()(分组捕获) | \(\) | () |
|(逻辑或) | \| | | |
推荐使用 -E 选项
在 GNU sed 4.2+ 中,推荐使用 -E 选项启用扩展正则表达式。相比 BRE,ERE 减少了大量的反斜杠转义,代码更清晰易读。在所有新编写的 sed 命令中,建议默认加上 -E 选项。
4.2 基本正则表达式的匹配
sed -n '/^#/p' config.ini
sed -n '/\.$/p' file.txt
sed -n '/c.t/p' file.txt
sed -n '/[0-9]/p' file.txt
sed -n '/[A-Za-z]/p' file.txt
sed -n '/[^0-9]/p' file.txt
sed -n '/ab*c/p' file.txt
sed -n '/ab\+c/p' file.txt
4.3 扩展正则表达式的匹配
sed -E -n '/ab+c/p' file.txt
sed -E -n '/colou?r/p' file.txt
sed -E -n '/[0-9]{3,5}/p' file.txt
sed -E -n '/^.{10,20}$/p' file.txt
sed -E -n '/(ab)+/p' file.txt
sed -E -n '/error|warning|fatal/p' log.txt
sed -E -n '/\bword\b/p' file.txt
4.4 正则表达式替换实战
sed -E 's/^[[:space:]]+//' file.txt
sed -E 's/[[:space:]]+$//' file.txt
sed -E 's/^[[:space:]]+|[[:space:]]+$//g' file.txt
sed -E 's/[[:space:]]+/ /g' file.txt
sed -E 's/\b([a-zA-Z0-9._%+-]+)@/\1\@/' emails.txt
sed -E 's/([0-9]{1,3}\.){3}[0-9]{1,3}/\1***/' access.log
sed -E 's/^# (.*)/
\1<\/h1>/' file.md
sed -E 's/^## (.*)/\1<\/h2>/' file.md
sed -E 's/^### (.*)/\1<\/h3>/' file.md
sed -E 's/\[([^\]]+)\]\(([^)]+)\)/\1<\/a>/g' file.md
4.5 POSIX 字符类
sed 支持 POSIX 字符类,这些类在各种语言环境中使用,比字符集 [a-z] 更可靠。
| 字符类 | 说明 | 等价写法 |
[[:alnum:]] | 字母和数字 | [a-zA-Z0-9] |
[[:alpha:]] | 字母 | [a-zA-Z] |
[[:digit:]] | 数字 | [0-9] |
[[:lower:]] | 小写字母 | [a-z] |
[[:upper:]] | 大写字母 | [A-Z] |
[[:space:]] | 空白字符 | 空格、Tab、换行等 |
[[:punct:]] | 标点符号 | [.,!?:;...] |
[[:blank:]] | 空格和 Tab | [ \t] |
[[:print:]] | 可打印字符 | [ -~] |
sed -E 's/[[:digit:]]+//g' file.txt
sed -E 's/[[:punct:]]+/ /g' file.txt
sed -E 's/[[:upper:]]/\L&/g' file.txt
sed -E '/^[[:space:]]*$/d' file.txt
五、替换操作详解
5.1 s 命令完整语法
s 命令是 sed 中使用频率最高的命令,其完整语法为:
[地址范围]s/模式/替换/[标志]
5.2 替换分隔符的选择
默认分隔符是 /,但当模式或替换文本中包含斜杠时,可以使用其他字符作为分隔符,提高可读性。
sed 's/\/usr\/local\/bin/\/usr\/bin/g' file.txt
sed 's#/usr/local/bin#/usr/bin#g' file.txt
sed 's|/usr/local/bin|/usr/bin|g' file.txt
sed 's@http://example.com@https://example.com@g' file.txt
sed 's_old_value_new_value_g' file.txt
分隔符选择原则:
选择替换模式中不会出现的字符作为分隔符。如果替换路径,用 # 或 |;替换 URL,用 @。这样可以完全避免转义,让代码更清晰。
5.3 替换标志详解
| 标志 | 含义 | 示例 | 说明 |
g | 全局替换 | s/old/new/g | 替换行内所有匹配(默认只替换第一个) |
N | 第 N 次匹配 | s/old/new/2 | 只替换行内的第 N 次匹配 |
p | 打印 | s/old/new/p | 仅打印成功替换的行(需配合 -n) |
w | 写入文件 | s/old/new/w out.txt | 将替换成功的行写入文件 |
i | 忽略大小写 | s/old/new/i | GNU sed 支持,不区分大小写 |
e | 执行命令 | s/.*/echo &/e | GNU sed 扩展,将替换结果作为命令执行 |
sed 's/foo/bar/' file.txt
sed 's/foo/bar/g' file.txt
sed 's/foo/bar/2' file.txt
sed -n 's/foo/bar/p' file.txt
sed -n 's/foo/bar/w out.txt' file.txt
sed -n 's/foo/bar/ip' file.txt
sed 's/foo/bar/gi' file.txt
sed 's/foo/bar/2g' file.txt
5.4 反向引用
反向引用允许在替换文本中引用模式中捕获组匹配的内容。在 BRE 中使用 \(\) 捕获,\1 到 \9 引用;在 ERE 中使用 () 捕获。
sed -E 's/^([^:]+):(.*)/\2:\1/' file.txt
echo "张, 三" | sed -E 's/([^,]+), (.+)/\2 \1/'
echo "1234567" | sed -E 's/([0-9])([0-9]{3})$/\1,\2/'
echo "1234567890" | sed -E ':a; s/([0-9]+)([0-9]{3})/\1,\2/; ta'
sed 's/[0-9]\+/(&)/g' file.txt
sed 's/[A-Z]\+/**&**/g' file.txt
echo "2024-03-15" | sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\3\/\2\/\1/'
sed -E 's/\b([A-Za-z]+) \1\b/\1/g' file.txt
5.5 替换中的转义序列
在替换文本中,可以使用一些特殊转义序列(GNU sed 支持):
| 序列 | 含义 | 说明 |
\1 到 \9 | 反向引用 | 引用第 1 到第 9 个捕获组 |
\& | 整个匹配 | 引用整个正则表达式的匹配内容 |
\U | 转大写 | 将后续字符转换为大写 |
\L | 转小写 | 将后续字符转换为小写 |
\E | 结束转换 | 停止 \U 或 \L 的大小写转换 |
\u | 首字母大写 | 将下一个字符转为大写 |
\l | 首字母小写 | 将下一个字符转为小写 |
echo "hello world" | sed 's/.*/\U&/'
echo "HELLO WORLD" | sed 's/.*/\L&/'
echo "hello world" | sed 's/\b\w/\u&/g'
echo "user_name" | sed -E 's/_([a-z])/\u\1/g'
echo "background-color" | sed -E 's/-([a-z])/\u\1/g'
5.6 实战:批量替换配置文件的典型场景
sed -i 's/Listen 80/Listen 8080/' /etc/apache2/ports.conf
sed -i 's|DB_HOST=localhost|DB_HOST=db.example.com|g' .env
sed -i 's|DB_PASSWORD=oldpass|DB_PASSWORD=newpass|g' .env
sed -i 's/version = "1\.0\.0"/version = "1.0.1"/' setup.py
sed -i '/^debug:/s/^debug:/# debug:/' config.yml
sed -E 's/^([^=]+)=([^"].*[^"])$/\1="\2"/' config.ini
for f in *.txt; do
mv "$f" "$(echo "$f" | sed 's/ /_/g')"
done
六、地址范围与行选择
6.1 地址类型概览
地址(address)用于指定 sed 命令作用于哪些行。地址可以是行号、正则表达式或特殊符号。
| 地址类型 | 语法 | 示例 | 含义 |
| 数字行号 | N | 3d | 只对第 3 行执行 |
| 行号范围 | N,M | 3,6d | 对第 3 到第 6 行执行 |
| 步进模式 | N~M | 1~2p | 从第 N 行开始,每 M 行执行一次 |
| 正则模式 | /regex/ | /^$/d | 匹配正则表达式的行 |
| 最后一行 | $ | $d | 最后一行 |
| 取反 | ! | 3!d | 除了第 3 行以外的所有行 |
6.2 行号模式详解
sed -n '1p' file.txt
sed -n '5p' file.txt
sed -n '5,10p' file.txt
sed '5,10d' file.txt
sed '5,10s/foo/bar/g' file.txt
sed -n '100,$p' file.txt
sed '100,$d' file.txt
sed -n '1~2p' file.txt
sed -n '2~2p' file.txt
sed -n '3~5p' file.txt
sed -n '5!p' file.txt
sed '5,10!d' file.txt
sed '/^#/!d' file.txt
6.3 正则模式匹配地址
sed -n '/ERROR/p' log.txt
sed '/^$/d' file.txt
sed -n '//,/<\/body>/p' index.html
sed -n '/START/,/END/p' file.txt
sed -n '/ERROR/,+5p' log.txt
sed -n '/ERROR/,/^$/p' log.txt
sed '/BEGIN/,/END/!d' file.txt
sed -e '/pattern1/d' -e '/pattern2/d' file.txt
sed '/pattern1/{/pattern2/d}' file.txt
模式范围的工作原理
当 sed 遇到形如 /addr1/,/addr2/ 的地址范围时,它会从匹配 addr1 的第一行开始激活命令,一直持续到匹配 addr2 的行为止。如果文件中有多个这样的范围,每个范围都会被处理。这种机制非常适合提取日志中的异常堆栈、配置文件块或者 HTML 片段。
6.4 地址范围与替换的组合
sed '1,10s/old/new/g' file.txt
sed '/\[database\]/,/\[/s/host/localhost/g' config.ini
sed '/^$/!s/old/new/g' file.txt
sed '/^# Custom Settings/,$s/^# //' config.ini
sed '10~3s/foo/bar/g' file.txt
6.5 练习案例:处理配置文件
sed '/\[database\]/,/^\[/{s/host = .*/host = new_host/}' config.ini
sed '/\[database\]/a\timeout = 30' config.ini
sed '/\[cache\]/,/^\[/{/^\[/!d}' config.ini
七、高级命令(分支、测试、标签)
7.1 标签与分支(b 命令)
sed 支持类似汇编语言的标签和分支机制,可以实现条件执行和循环处理。
sed ':label 命令序列 b label' file.txt
sed '/^#/b; s/foo/bar/g' file.txt
sed '/^START/b output; s/.*/prefix_&/; :output' file.txt
sed '/^#/b end; s/foo/bar/; :end' file.txt
7.2 测试命令(t 命令)
t 命令在最近一次替换成功时跳转到指定的标签。这是实现循环替换的关键命令。
sed ':label s/模式/替换/ t label' file.txt
sed ':a; s/ / /g; ta' file.txt
echo "1234567890" | sed ':a; s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/; ta'
echo "1234567890" | sed -E ':a; s/([0-9]+)([0-9]{3})/\1,\2/; ta'
sed ':a; s/old/new/; ta; s/another/different/' file.txt
b vs t 的区别:
b(branch)是无条件分支,遇到就跳转。而 t(test)是有条件分支,只有当前行上一次 s 替换操作成功时才跳转。通常 t 用于实现递归替换(循环直到没有可替换的内容),b 用于条件判断和跳过逻辑。
7.3 替换命令(y 命令)
y 命令用于字符级替换(类似 tr 命令),将一组字符逐一映射到另一组字符。
sed 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' file.txt
tr 'a-z' 'A-Z' < file.txt
sed 'y/[]/()/' file.txt
sed 'y/\t/ /' file.txt
sed 'y/\r//' file.txt
7.4 其他高级命令
sed -n '/ERROR/=' log.txt
sed -n '/^$/=; p' file.txt
sed -n 'l' file.txt
sed '/pattern/{n; s/foo/bar/;}' file.txt
sed 'N; s/\n/ /' file.txt
sed '/ERROR/q' log.txt
sed '100q' bigfile.txt
7.5 实战:电话号码格式化
echo "13812345678" | sed -E 's/([0-9]{3})([0-9]{4})([0-9]{4})/\1-\2-\3/'
echo "13812345678" | sed -E ':a; s/([0-9]+)([0-9]{4})/\1-\2/; ta'
sed -E 's/(1[3-9][0-9])([0-9]{4})([0-9]{4})/\1-\2-\3/g' contacts.txt
八、多行模式处理
8.1 模式空间与保持空间概述
sed 有两个内部存储缓冲区:模式空间(pattern space)和保持空间(hold space)。模式空间是主工作区,每一行文本都会先被读入模式空间。保持空间是一个辅助缓冲区,可以暂存数据以便后续处理。
| 命令 | 全称 | 作用 |
h | hold | 将模式空间的内容复制到保持空间(覆盖) |
H | Hold | 将模式空间的内容追加到保持空间 |
g | get | 将保持空间的内容复制到模式空间(覆盖) |
G | Get | 将保持空间的内容追加到模式空间 |
x | exchange | 交换模式空间和保持空间的内容 |
n | next | 读取下一行到模式空间(覆盖当前内容) |
N | Next | 将下一行追加到模式空间(用 \n 分隔) |
P | Print | 打印模式空间的第一行(到第一个 \n 为止) |
D | Delete | 删除模式空间的第一行(到第一个 \n 为止) |
8.2 N 命令:多行合并处理
N 命令将下一行读取并追加到当前模式空间中,中间用换行符 \n 分隔。这允许跨行匹配模式。
sed 'N; s/\n/ /' file.txt
sed ':a; N; $!ba; s/\n/ /g' file.txt
sed '/hello/{ N; s/hello\nworld/hello world/; }' file.txt
sed '/pattern/{ N; s/\n/\n\n/; }' file.txt
sed '/,$/{ N; s/,\n/, /; }' file.txt
8.3 保持空间的应用
保持空间最常见的用途是实现"颠倒输出"和"累积匹配行"。
sed '1!G; h; $!d' file.txt
sed '${p; :a; N; /^\n.*\n.*\n.*\n.*\n.*\n.*\n.*\n.*\n.*\n$/!ba; s/.*\n//; p}' file.txt
sed 'H; $!d; ${ x; s/^\n//; }' file.txt | tail -10
sed -n '/ERROR/{ H; }; ${ x; s/^\n//; p; }' log.txt
paste -d '\n' file1.txt file2.txt | sed 'N; s/\n/ | /'
理解 sed 的"颠倒"过程
sed '1!G; h; $!d' 这个看似神秘的命令是这样工作的:
- 读取第 1 行时:跳过 G,用 h 保存到保持空间,然后 d 删除(不输出)。保持空间现在有第 1 行。
- 读取第 2 行时:执行 G(将保持空间内容追加到模式空间,模式空间变为"第2行\n第1行"),h 将合并结果保存到保持空间,d 删除。保持空间有"第2行\n第1行"。
- 继续处理,保持空间永远存储着"当前行\n之前的所有行"。
- 最后一行($)时:不执行 d,模式空间的内容("最后一行\n...\n第一行")被自动输出。
8.4 D 和 P 命令:部分操作
D 和 P 命令只处理模式空间中的第一行(第一个换行符之前的内容),常与 N 命令配合。
sed 'N; /pattern/{ D; }; P; D' file.txt
sed '/PATTERN/!d; N; N; N; /PATTERN.*\n.*\n.*\n$/P; D' file.txt
sed -n 'N; P' file.txt
sed '/^$/!{ H; d; }; x; s/^\n//; /pattern/p' file.txt
8.5 实战:提取特定段落
sed -n '/^$/!{ H; d; }; x; s/^\n//; /ERROR/p; s/.*//; h' log.txt
sed -n '//,/<\/chapter>/p' book.xml
sed -n '/^[^$]/{ H; }; /^$/{ x; s/^\n//; p; s/.*//; h; }' log.txt
九、脚本化与实用技巧
9.1 使用 sed 脚本文件
当 sed 命令非常复杂时,可以将其写入脚本文件,通过 -f 选项调用。
sed -f process.sed input.txt > output.txt
sed -f clean_config.sed config.ini
9.2 管道中的 sed
sed 经常在管道中与其他命令组合使用,形成强大的数据处理流水线。
grep -rn "TODO" src/ | sed 's/:/ | /' | sort
cat /sys/class/thermal/thermal_zone*/temp |
sed 's/\(...\)$/.&°C/' |
head -1
cat access.log |
sed -n '/5[0-9][0-9]/p' |
sed -E 's/.* ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+) .*/\1/' |
sort | uniq -c | sort -rn |
head -10
find . -name "*.html" -exec sed -i 's/old.css/new.css/g' {} \;
grep -rl "old_text" --include="*.py" . | xargs sed -i 's/old_text/new_text/g'
ifconfig | sed -n '/inet /s/.*inet \([0-9.]*\).*/\1/p'
9.3 sed 实用工具函数
以下是一些可以放入 Shell 脚本中的 sed 工具函数:
clean_config() {
sed -E '/^[[:space:]]*(#|$)/d' "$1"
}
number_lines() {
sed -n '/./=' "$1" | sed 'N; s/\n/ /'
}
number_lines_v2() {
sed -n '$!N; s/^/& /' "$1"
}
tab_to_space() {
sed 's/\t/ /g' "$1"
}
trim_trailing() {
sed -i 's/[[:space:]]*$//' "$1"
}
number_headers() {
local count=0
sed -E '/^## /{ s/^## /&'$((++count))'. /; }' "$1"
}
extract_between() {
sed -n "/$1/,/$2/p" "$3"
}
9.4 高效技巧集锦
sed -n 's/.*\.\([a-zA-Z-]*\).*/\1/p' style.css | sort -u
sed 's/[^ ]/o/g' file.txt | sed 's/ //g;s/o/./g' | sed -n 's/./&/gp' | wc -c
sed -E 's/^([^,]*),([^,]*),([^,]*),([^,]*),(.*)/\2 \5/' data.csv
sed -E 's/"([A-Z][^"]*)":/\L\1:/g' data.json
sed '5~5i\----------------------------------------' file.txt
sed 's/.*/
&<\/li>/' items.txt > list.html
sed '1i\' list.html > list2.html
sed '$a\<\/ul>' list2.html > final.html
sed 's/pattern/replacement/' file.txt 2>&1
echo "$PATH" | sed 'y/:/\n/'
sed '/