陈颂光
全栈工程师,承接从编译器到网站的各类软件开发与咨询,也可以聊历史哲学。
关注我的 GitHub

sed概览

sed是一个流编辑器,只过输入一遍,用于过滤和转换文本。

用法

sed [OPTION]... {script-only-if-no-other-script} [input-file]...
选项 意义
-n, –quiet, –silent 不自动打印模式空间
-e script, –expression=script 加入命令
-f script-file, –file=script-file 加入命令
–follow-symlinks 原地处理时跟随符号链接
-i[SUFFIX], –in-place[=SUFFIX] 原地处理,有 SUFFIX 则备份原文件
-l N, –line-length=N 指定l命令所需的行长度
–posix 关闭GNU扩展
-r, –regexp-extended 用扩展正则表达式
-s, –separate 分别处理每个文件而非串起
-u, –unbuffered 最小输入缓冲
-z, –null-data 用 NUL 分隔行
–help 打印帮助并退出
–version 打印版本并退出

没有-e, –expression, -f, 或 –file 选项时,首个非选项的参数为sed命令脚本。所有其它参数为输入文件,不指定则用标准输入。

当然sed也可以用来写Unix脚本,这时首行形如:

#!/usr/bin/sed -nf

命令

sed脚本由一系列命令组成,用分号或换行分隔。每条命令由可选的地址或地址范围、一个字符的命令名和命令相关参数组成。

零个的地址命令

命令格式 用途
: label 作标记
#comment 行末注释
} 结束块

零或一个地址的命令

命令格式 用途
= 打印当前行号
a text 附加文本,其中换行前应加反斜杠
i text 插入文本,其中换行前应加反斜杠
q [exit-code] 不再处理更多输入并打印当前模式空间退出
Q [exit-code] 不再处理更多输入并退出
r filename 附加来自filename的文本
R filename 附加来自filename的一行文本

接受地址范围的命令

命令格式 用途
{ 开始块
b label 转到标记label,不指定则转到脚本结束
c text 替换为text,其中换行前应加反斜杠
d 删除模式空间,开始下一迭代
D 若模式空间无换行,删除模式空间,开始下一迭代。否则,删除模式空间首行重启迭代
h H 从模式空间复制或附加到暂存空间
g G 从暂存空间复制或附加到模式空间
l 列出当前行
l width 列出当前行并作断行
n N 读入或附加下一输入行到模式空间
p 打印当前模式空间
P 打印当前模式空间到首个换行
s/regexp/replacement/flag 把匹配regexp的部分替换为replacement,其中可用&引用匹配部分,用\1到\9匹配捕获组
t label 若自从读入最近一行和上一t或T命令,有一个s///作出了成功的替换,则转到标记label,不指定则转到脚本结束
T label 若自从读入最近一行和上一t或T命令,没有一个s///作出了成功的替换,则转到标记label,不指定则转到脚本结束
w filename 把当前模式空间首行写入filename
W filename 把当前模式空间首行写入filename
x 交换暂存空间和模式空间
y/source/dest/ 把模式空间中source中字符换成dest中对应字符

其中s命令的flag可由以下字符组成:

标记 用途
g 全部替换
NUMBER 只替换第NUMBER个匹配
p 打印发生替换后的模式空间
w FILE-NAME 写入替换结果到文件
e 替换后执行模式空间并把模式空间换成其输出
I或i 大小写不敏感
M或m 多行模式

地址

没有地址则对所有输入行执行命令。

有一个则仅对匹配地址的输入行执行命令。其中地址形如:

地址 意义
number 行号为number(可跨文件)
first~step 从行号为first(0相当于step)的行开始每step行
$ 最后一行
/regexp/ 匹配正则表达式regexp的行,后接I导致大小写不敏感,后接M导致多行模式
\%cregexp% 匹配正则表达式regexp的行,%可以为任何字符,后接I导致大小写不敏感,后接M导致多行模式

有两个则仅对匹配地址范围的输入行执行命令,给定地址addr1和addr2,两地址形式如下:

两地址形式 意义
addr1,addr2 从匹配addr1的行到匹配addr2的行(含),若addr2为正则表达式,不会与addr1的行匹配
0,addr2 从开始到匹配addr2的行(含)
addr1,+N 匹配addr1的行和下面N行
addr1,~N 匹配addr1的行直到行号为N的倍数的行(含)

在地址或两地址形式后加上!将导致匹配结果反转。

应用

由于提供的操作较底层,sed的使用可以很有技巧性,涉及算术时就很不自然。以下是一些相对简单的例子:

目的 sed方法 其它方法
反转行顺序 sed -n '1!G;$p;h' tac
打印前十行 sed '10q' head
打印末十行 sed -n '1!{;H;g;};1,10!s/[^\n]*\n//;$p;h' tail
去除相邻的重复行 sed 'h;:b;$b;N;/^\(.*\)\n\1$/{;g;bb;};$b;P;D' uniq
去除空白行 sed -n '/^[:space:]*$/!p'  
统计行数 sed -n '$=' wc -l
关键词 unix sed