与 vim 不同,sed 是一种非交互式的文本编辑器,同时它又是面向字符流的,每行数据经过 sed 处理后输出。
|
|
sed 的工作过程是这样的:首先,初始化两个数据缓冲区模式空间和保持空间;sed 读取一行输入 (来自标准输入或文件),去掉结尾的换行符(\n) 后置于模式空间中,然后针对模式空间中的字符串开始执行‘sed 命令’,每个命令都可以有地址与之相关联,地址可以看成是条件,只有在条件成立时,相关的命令才被执行;所有可执行命令都处理完毕后,仍处于模式空间中的字符串会被追加一个换行符后打印输出;之后读取下一行输入做同样的处理,直到主动退出 (q) 或输入结束。
地址
地址可以是如下的形式
- number 表示行号
- first~step 表示从 first(数字) 行开始,每隔 step(数字) 行
- $ 表示最后一行 (注意当出现在正则表达式中时表示行尾)
- /regexp/ 表示匹配正则表达式 regexp(关于正则表达式,请参见这一篇)
- \%regexp% 表示匹配正则表达式 regexp,% 可以换成任意其他单个字符。(用于 regexp 包含斜线 / 的情况)
- /regexp/I 匹配正则表达式 regexp 时不区分大小写
- /regexp/M 启用正则多行模式,使 $ 不止匹配行尾,还匹配 n 或 r 之前的位置;使 ^ 不止匹配行首,还匹配 n 或 r 之后的位置。此时可以用(`)匹配模式空间的开头位置,用(\’)匹配模式空间的结束位置。
还可以用逗号, 分隔两个地址来表示一个范围
表示从匹配第一个地址开始,直到匹配第二个地址或文件结尾为止。如果第二个地址是个正则表达式,则不会对第一个地址匹配行进行第二个地址的匹配;如果第二个地址是行号,但小于或等于第一个地址匹配行行号,则只会匹配一行 (第一个地址匹配行)。
- 0,/regexp/ 这种情况下,正则表达式 regexp 会在第一行就开始进行匹配。只有第二个地址是正则表达式时,第一个地址才能用 0。
- addr1,+n 表示匹配地址 addr1 和其后的 n 行。
- addr1,~n 表示从匹配地址 addr1 开始,直到 n 的倍数行为止。
如果没有给出地址,所有的行都会匹配;在地址或地址范围后追加字符! 表示对地址取反,所有不匹配的行才会被处理。
选项
- -n 默认时每一行处理过的字符串都会被打印输出,此选项表示关闭此默认行为。只有被命令 p 作用的字符串才会被输出。
- -f file 表示从 file 中读取 sed 命令
- -i 表示原地修改。应用此选项时,sed 会创建一个临时文件,并将处理结果输出到此文件,处理完毕后,会将此临时文件覆盖至原文件。
- -r 表示使用扩展的正则表达式
命令
p 表示打印模式空间内容,通常配合选项 -n 一起使用
|
|
d 删除模式空间内容,立即处理下一行输入。
|
|
q 立即退出,不再处理任何命令和输入 (只接受单个地址)
|
|
n 如果没有使用选项 -n,输出模式空间中内容后,读取下一行输入并覆盖当前模式空间内容。如果没有更多的输入行,sed 会退出执行。
|
|
s/regexp/replacement/flag 表示用 replacement 替换模式空间中匹配正则表达式 regexp 的部分。在这里符号 / 可以换成任意单个字符。
|
|
在 replacement 中
1、\n (n 为 1-9 中的一个数字)表示对正则表达式中分组 (…) 的引用;
|
|
2、& 表示模式空间中所有匹配 regexp 的部分;
|
|
3、\L 将后面的字符转化成小写直到 \U 或 \E 出现;
4、\l 将下一个字符转化为小写;
5、\U 将后面的字符转化成大写直到 \L 或 \E 出现;
6、\u 将下一个字符转化为大写;
7、\E 停止由 \L 或 \U 起始的大小写转化;
|
|
flag
1、n 数字 n 表示替换第 n 个匹配项
|
|
2、g 表示全局替换
|
|
3、p 表示如果替换成功,则打印模式空间内容。
4、w file 表示如果替换成功,则输出模式空间内容至文件 file 中。
5、I 和 i 表示匹配 regexp 时不区分大小写。
|
|
6、M 和 m 表示启用正则多行模式 (如前所述)。(讲命令 N 时再举例)
y/source-chars/dest-chars/ 把 source-chars 中的字符替换为 dest-chars 中对应位置的字符,/ 可以换为其他任意单个字符,source-chars 和 dest-chars 中字符数量必须一致且不能用正则表达式。
|
|
a text 表示输出模式空间内容后追加输出 text 内容
|
|
i text 表示输出模式空间内容之前,先输出 text 内容
|
|
c text 表示删除匹配地址或地址范围的模式空间内容,输出 text 内容。如果是单地址,则每个匹配行都输出,如果是地址范围,则只输出一次。
|
|
= 表示打印当前输入行行号
|
|
r file 表示读取 file 的内容,并在当前模式空间内容输出之后输出
|
|
D 如果模式空间中没有新行 (如命令 N 产生的新行),则和命令 d 起同样作用;如果包含新行,则会删除第一行内容,然后对模式空间中剩余内容重新开始一轮处理。(注意:D 后面的命令将会被忽略)
|
|
P 打印模式空间中第一行内容
|
|
g 用保持空间中的内容替换模式空间中的内容
|
|
G 追加一个换行符到模式空间,然后再将保持空间中的内容追加至换行符之后。(此时模式空间中内容形如 PATTERN\nHOLD)*
|
|
h 用模式空间中的内容替换保持空间中的内容 (注意此时模式空间中的内容并没有被清除)
|
|
H 追加一个换行符到保持空间,然后再将模式空间中的内容追加至换行符之后。(此时保持空间中内容形如 HOLD\nPATTERN)
|
|
x 交换模式空间和保持空间的内容
|
|
: label 为分支命令指定标签位置 (不允许地址匹配)
b label 无条件跳转到 label 分支,如果省略了 label,则跳转到整条命令结尾 (即开始下一次读入)
|
|
t label 在一次输入后有成功执行的 s 替换命令才跳转到 label,如果省略了 label,则跳转到整条命令结尾 (即开始下一次读入)
|
|
T label 在一次输入后只要没有替换命令被成功执行就跳转到 label,如果省略了 label,则跳转到整条命令结尾 (即开始下一次读入)
z 表示清除模式空间中内容,和 s/.*// 起相同的作用,但更有效。
更多例子
1、删除匹配行的上一行和下一行
|
|
2、合并奇偶数行
|
|
3、合并多文件
|
|
为加深对 sed 各种命令特性的理解,请自行分析这三个例子。
各种命令的组合使用,再加上正则表达式的强大能力,使得sed可以处理所有能够计算的问题。但由于代码可读性不强,理解起来比较困难,通常使用sed作为一个文本编辑器,对文本做非交互的流式处理。理解上述各个命令的含义,熟练使用它们,就会发现sed的强大之处。