一、SED介绍
SED(Stream EDitor)是一个文本解析转换工具。它遵循简单的工作流:读取、执行、显示。
- 读取:SED从输入流(文件,管道或者标准输入)中读取一行并且存储到模式空间(pattern buffer)的内部缓冲区
- 执行:默认情况下,所有的SED命令都在模式空间中顺序执行;而且SED命令将会在所有的行上依次执行,除非指定了行的地址
- 显示:发送修改后的内容到输出流。在发送数据之后,模式空间将会被清空
注意
- 模式空间是一块缓冲区,在sed编辑器执行命令时会保存待检查的文本
- 默认情况下,所有的sed命令都是在模式空间中执行,因此输入文件并不会发生改变
- 还有另外一个缓冲区叫做保持空间(hold buffer),在处理模式空间中的某些行时,可以用保持空间来临时保存一些行。在每一个循环结束的时候,sed会移除模式空间中的内容,但是该缓冲区中的内容在所有的循环过程中是持久存储的。
示例
首先查看quote.txt文件内容:
执行sed '' quote.txt
结果如下:
处理流程:sed命令先将文本中的一行内容存储到它的模式空间中,然后在缓冲区执行命令;此处没有提供sed命令,所以对该缓冲区没有要执行的操作;最后删除模式空间的内容,并打印该内容到标准输出。最后流程总结如下:
一行内容->模式空间->执行命令->删除模式空间内容->打印
二、使用
2.1 基础语法
sed -option 'command' file
2.1.1 命令说明
command | 说明 |
---|---|
d | 删除 (delete) |
s | 单个字符替换 (substitute) |
p | 打印 (print) |
w | 写入 (write)命令 |
a | 追加 (append) |
c | 行替换 (change) |
i | 插入 (insert) |
l | 显示隐藏字符 |
q | 退出命令 (quit) |
r | 文件读取 (read) |
e | 执行外部命令 |
! | 排除命令 |
-
d
books.txt内容如下:
执行sed '2d' books.txt
命令,删除第二行内容:
-
s
执行sed 's/$/!/'
命令,给books.txt文件每一行结尾加上感叹号:
-
p
首先看sed 'p' quote.txt
命令执行结果:
同sed '' quote.txt
命令相比,每一行打印了两次,这是因为在内容读取进模式空间进行处理的时候,执行的命令是p
,打印内容(第一次),在处理完毕之后,模式空间的内容又打印到标准输出(第二次)。
可以使用-n
参数来抑制第二次的打印行为,sed -n 'p' quote.txt
执行结果如下,同sed '' quote.txt
命令结果相同:
- w
语法
[address] w file
file是要写入的文件名,如果文件名不存在,则会自动创建,如果已经存在,则会覆盖原内容
观察以下两条示例:
sed -n 'w books.bak' books.txt
,由于没有指定地址,那么会将文件books.txt的所有内容都写入到新文件中。
sed -n '2,3 w junk.txt' books.txt
,将2到3行内容写到新文件中
- a
sed '$a 7) my append txt' books.txt
,给最后一行追加内容
- c
当提供行的地址范围时,所有行都被作为一组替换成单行文本
sed '2,3c they are changed' books.txt
命令,替换2,3行内容:
- i
sed '1i insert txt' books.txt
,给第一行插入内容,插入到前一行:
- l
sed 's/ /\t/g' books.txt > junk.txt
,首先将books.txt中的空格替换成/t
sed -n 'l' junk.txt
,查看junk.txt文件的隐藏字符
此外,l
命令还能让文本按照指定的宽度换行:
sed -n 'l 40' books.txt
,文本中的每一行如果超过40字符,则换行:
- q
语法
[address]q [value]
只支持单个地址匹配
value作为程序的返回,可以写也可不写
sed '3q 6' books.txt
,匹配第三行退出,返回值6:
- r
r
命令可以从外部文件中读取内容,并在满足条件的时候显示
[address]r file
sed '3r junk.txt' books.txt
,将junk.txt文件内容在第三行之后显示:
- e
sed '3e date' books.txt
,执行外部命令date:
- !
使原来起作用的命令不起作用
sed '/Paulo/!p' books.txt
:
2.1.2 参数说明
option | 说明 |
---|---|
-n | 抑制输出 |
-e | 执行多条命令 |
-f | 执行指定脚本文件里的命令 |
- -n
默认情况下,模式空间的内容在处理完毕之后将会打印到标准输出,该选项用于阻止该行为。
可以查看sed '' quote.txt
命令加-n参数和不加参数的情况如下
- -e
使用-e选项,执行多次删除命令,sed -e '2d;5d' books.txt
- -f
脚本文件内容如下,即删除第二行和第五行内容:
执行sed -f testCommand books.txt
命令,结果中删除了第二行和第五行内容,说明命令生效:
2.2 循环和分支
sed提供用于控制执行流的循环和分支语句
2.2.1 循环
sed可以根据标签(label)跳转到某一行继续执行;我们可以定义如下标签:
:label
:start
:end
:up
定义完标签之后,如果要跳转到指定的标签,使用b命令后跟着标签名;如果忽略标签名,sed将会跳转到sed文件的结尾。
b start -->表示跳转到start标签的位置
- 示例
首先查看示例文件books2.txt的内容:
执行以下命令:
root@iZwz98umwfu68refxh45n0Z:/opt/shell/sed-demo-master# sed -n '
> h;n;H;x
> s/\n/,/
> /Paulo/!b Print
> s/^/-/
> :Print
> p' books2.txt
结果:
命令分析:
- 第一行
h;n;H;x
命令,h
是指将当前模式空间中的内容覆盖到保持空间中;n
是用于提前读取下一行,并覆盖当前模式空间中的这一行;H
将当前模式空间的内容追加到保持空间;x
用于交换模式空间和保持空间中的内容。最终达到的效果就是每次读取两行放到模式空间中进行处理。 - 第二行
s/\n/,/
命令用于将上面的两行内容进行处理,把换行符替换成逗号。 - 第三行
/Paulo/!b Print
命令,进行匹配,如果不满足匹配条件,则跳转到Print标签,否则执行第四行命令。 - 第四行
s/^/-/
命令,将这一行的开头添加-
- 第五行
:Print
只是一个标签名 - 第六行
p
,打印命令;
不符合匹配条件的执行流,过程为2->3->5->6
;符合匹配条件的执行流,2->3->4->5->6
,两者区别只是是否少了第四行命令而已,也就是说,标签后的内容,都是一样要执行的。
以上的命令也可以写在同一行:
sed -n 'h;n;H;x;s/\n/,/;/Paulo/!b Print;s/^/-/;:Print;s/^/!/;p' books2.txt
2.2.2 分支
使用t命令创建分支,只有当前置条件成功的时候,t命令才会跳转到该标签。
前置条件:替换(s)命令执行成功
- 示例
执行命令
sed -n '
> h;n;H;x
> s/\n/,/
> :loop
> /Paulo/s/^/-/
> /----/!t loop
> p' books2.txt
结果:
命令分析(前两行与以上示例一致):
- 第三行
:loop
,定义了一个loop标签 - 第四行
/Paulo/s/^/-/
,匹配存在Paulo的行,如果存在则在开头添加一个-
- 第五行
/----/!t loop
(重点),检查上面添加-
之后,是否满足有四个-
,如果不满足,则跳到第三行,继续往下执行,再向最前面添加一个-
;如果满足,则向下执行p
命令。
所以此示例的前置条件就是第四行命令中的s
命令执行成功,才会继续第五行命令。如果第四行命令没有执行成功,则直接执行最后一行p
命令。
2.3 行寻址
sed中包含有以下两种形式的行寻址:
- 以数字形式表示的行区间
- 以文本模式来过滤行
以上两中方式的语法都相同
[address]command
2.3.1 数字方式行寻址
- 指定某一行,使用单独的数字
sed -n '3d' books.txt
,指定第三行执行d
命令 - 指定行的范围,起始行和结束行之间用逗号隔开
sed -n '2,5 p' books.txt
,第二行到第五行执行p
命令 - $代表文件最后一行
M,+n
,选定第M行开始的下n行
M~n
,选定M行开始的每n行
2.3.2 文本模式过滤
/pattern/command
,使用/符号来开启匹配,同时以/符号结束
2.4 多行命令
sed编辑器执行基础命令时,会基于换行符的位置将数据分成多行,一次处理一行的数据,然后移到下一行重复这个过程。
但是sed编辑器也有用来处理多行文本的特殊命令
命令 | 说明 |
---|---|
N | 将数据流中的下一行追加进来组成多行组一起处理 |
P | 输出多行文本的模式空间中的第一行 |
2.4.1 N - 加载下一行
sed 'N;s/\n/,/' books2.txt
2.4.2 P - 输出第一行
sed -n 'N;P' books2.txt
2.5 特殊字符
sed中含有两个可以用作命令的特殊字符:= 和**&**
2.5.1 =
命令
用于输出行号
sed -n '$n' books2.txt
,输出最后一行的行号:
三、正则表达式
3.1 定位符
字符 | 说明 |
---|---|
^ | 匹配行的开头 |
$ | 匹配行的结尾 |
- ^
sed '/^The/ p' books2.txt
- $
sed '/Coelho$/ p' books2.txt
3.2 特殊字符
字符 | 说明 |
---|---|
. | 匹配除了换行符以外的所有单个字符 |
- .
$ echo -e 'cat\ndog\nmat\nrats' | sed -n '/..t$/ p'
cat
mat
3.3 字符集相关
符号 | 说明 |
---|---|
[] | 匹配字符集 |
[^] | 排除字符集 |
[-] | 匹配字符范围 |
- []
- [^]
[^cn]
,排除出现c或者n字符 - [-]
[a-c]
,指出现a到c任一字符
3.4 限定符
字符 | 说明 |
---|---|
? | 匹配0次到1次 |
+ | 匹配一次到多次 |
* | 匹配0次到多次 |
{n} | 精确匹配n次 |
{n,} | 至少匹配n次 |
{n,m} | 匹配n-m次 |
3.5 元字符
字符 | 说明 |
---|---|
\s | 匹配单个空白内容 |
\S | 匹配单个非空白内容 |
\w | 匹配单个单词 |
\W | 匹配非单词 |