Sed
Section outline
-
sed(流编辑器)简介
sed
(stream editor,流编辑器)是 Unix 系统中的一个文本处理工具,可用于解析和转换文本文件,且支持多个操作系统。尽管在许多用途上已经被perl
(或更早的AWK
)取代,但sed
在 Shell 脚本中的简单文本转换仍然有一定的应用价值。sed
是面向行(line-oriented)的,它逐行处理输入,支持正则表达式匹配和替换。
1. sed 的基本使用
1.1
s
(substitution,替换)命令sed
最常用的功能是s
命令(替换),用于将一种模式替换为另一种模式,例如:sed 's/cat/dog/g' input.txt > output.txt
以上命令会将
input.txt
中的"cat"
替换为"dog"
,并输出到output.txt
。其中:s/cat/dog/
:将cat
替换为dog
g
(global):表示替换行内所有匹配项,而不仅仅是第一个
建议:使用单引号
''
避免 Shell 误解析特殊字符:sed 's/cat/dog/g' input.txt > output.txt
1.2 多个替换
可以使用
-e
选项进行多个模式替换:sed -e 's/cat/dog/g' -e 's/meow/woof/g' input.txt > output.txt
1.3
sed
作为管道处理sed
也可用于管道操作:echo "Hello cat" | sed 's/cat/dog/g'
输出:
Hello dog
2. 复杂模式匹配
2.1 扩展正则表达式
默认情况下,
sed
仅支持基本正则表达式(BRE),如需使用扩展正则表达式(ERE),需要:- GNU sed 使用
-r
- BSD sed(macOS 默认安装) 使用
-E
示例:
sed -r 's/<(.*)>/<\1><\/\1>/g' input.txt
以上命令会将
<a>
替换为<a></a>
。
2.2 组匹配与替换
使用
()
进行分组匹配,并在替换中使用\1, \2, ...
引用:echo "abc" | sed -r 's/(a)(b)(c)/\3\2\1/'
输出:
cba
3. 编程与高级用法
3.1 逐行操作
sed
逐行处理数据,每次仅处理一行。如需跨行操作,可使用:N
(读取下一行到缓冲区)H
和g
(存入/获取缓冲区)
3.2 合并多行
tr
命令比sed
更适合合并所有行:tr '\n' ' ' < input.txt > output.txt
tr
逐字符处理,不会占用大量内存,而sed
会加载整个文件到内存。
4. 相关命令
grep
:选择符合条件的行tr
:进行单字符转换awk
和perl
:处理复杂文本任务
5. sed 选项
5.1 POSIX
sed
选项-n # 仅通过 `p` 命令输出匹配内容 -e # 指定多个 `sed` 命令 -f # 从文件读取 `sed` 命令
5.2 GNU
sed
额外选项--version # 显示版本 --help # 显示帮助 --quiet, --silent # 与 `-n` 类似 --in-place[=SUFFIX] # 直接修改文件内容(可选备份) --regexp-extended, -r # 启用扩展正则
5.3 BSD
sed
额外选项(macOS 默认)-E # 启用扩展正则 -i # 直接修改文件内容(不支持 `--in-place`)
6. 正则表达式支持
sed
使用 POSIX 基本正则表达式(BRE),GNUsed
支持 扩展正则表达式(ERE):表达式 描述 *
匹配前面字符 0 次或多次 .
匹配任意单个字符 ^
匹配行首 $
匹配行尾 [abc]
匹配 a
、b
或c
[^abc]
匹配非 a
、b
、c
的字符\( \)
进行分组(适用于 \1, \2
){i,j}
匹配 i 到 j 次 \b
单词边界(GNU sed
扩展)
7. sed 一行命令(Oneliners)
7.1 简单替换
sed "s/concieve/conceive/" file.txt # 仅替换每行的第一个匹配项 sed "s/concieve/conceive/g" file.txt # 替换所有匹配项
7.2 多次替换
sed "s/concieve/conceive/g; s/recieve/receive/g" file.txt
7.3 使用组匹配
echo "abccbd" | sed -r "s/a([bc]*)d/\1/g" # 结果:bccb
7.4 处理日期格式
echo "03/11/2015 23:54:03" | sed -r "s/([0-9]+)\/([0-9]+)\/([0-9]+)/\3-\2-\1/g" # 结果:2015-11-03 23:54:03
7.5 处理引号
sed "s/\x22/'/g" file.txt # 将双引号 `"` 替换为单引号 `'`
7.6 忽略大小写
echo "Hallo" | sed "s/hallo/hello/gi" # 结果:hello
7.7 替换字母
echo "a2" | sed "s/[[:alpha:]]/z/g" # 结果:z2
8. sed 的局限性
- 不支持非贪婪匹配(
.*?
)echo "abcbbc" | perl -pe "s/a.*?c/ac/" # 结果:acbbc
- 不支持 Perl 风格的
\d, \D, \A, \Z
- GNU
sed
扩展特性不适用于所有sed
版本
🎯 总结:
sed
适用于行级别的文本转换,但复杂任务建议使用awk
或perl
。