SED(Stream EDitor)是一个文本解析转换工具。它遵循简单的工作流:读取、执行、显示。
首先查看quote.txt文件内容:
执行sed '' quote.txt
结果如下:
处理流程:sed命令先将文本中的一行内容存储到它的模式空间中,然后在缓冲区执行命令;此处没有提供sed命令,所以对该缓冲区没有要执行的操作;最后删除模式空间的内容,并打印该内容到标准输出。最后流程总结如下:
一行内容->模式空间->执行命令->删除模式空间内容->打印
sed -option 'command' file
command | 说明 |
---|---|
d | 删除 (delete) |
s | 单个字符替换 (substitute) |
p | 打印 (print) |
w | 写入 (write)命令 |
a | 追加 (append) |
c | 行替换 (change) |
i | 插入 (insert) |
l | 显示隐藏字符 |
q | 退出命令 (quit) |
r | 文件读取 (read) |
e | 执行外部命令 |
! | 排除命令 |
p
首先看sed 'p' quote.txt
命令执行结果:
同sed '' quote.txt
命令相比,每一行打印了两次,这是因为在内容读取进模式空间进行处理的时候,执行的命令是p
,打印内容(第一次),在处理完毕之后,模式空间的内容又打印到标准输出(第二次)。
可以使用-n
参数来抑制第二次的打印行为,sed -n 'p' quote.txt
执行结果如下,同sed '' quote.txt
命令结果相同:
[address] w file
file是要写入的文件名,如果文件名不存在,则会自动创建,如果已经存在,则会覆盖原内容
观察以下两条示例:
sed -n 'w books.bak' books.txt
,由于没有指定地址,那么会将文件books.txt的所有内容都写入到新文件中。
sed -n '2,3 w junk.txt' books.txt
,将2到3行内容写到新文件中
sed '2,3c they are changed' books.txt
命令,替换2,3行内容:
sed '1i insert txt' books.txt
,给第一行插入内容,插入到前一行:sed 's/ /\t/g' books.txt > junk.txt
,首先将books.txt中的空格替换成/tsed -n 'l' junk.txt
,查看junk.txt文件的隐藏字符l
命令还能让文本按照指定的宽度换行:sed -n 'l 40' books.txt
,文本中的每一行如果超过40字符,则换行:[address]q [value]
只支持单个地址匹配
value作为程序的返回,可以写也可不写
sed '3q 6' books.txt
,匹配第三行退出,返回值6:
r
命令可以从外部文件中读取内容,并在满足条件的时候显示[address]r file
sed '3r junk.txt' books.txt
,将junk.txt文件内容在第三行之后显示:
option | 说明 |
---|---|
-n | 抑制输出 |
-e | 执行多条命令 |
-f | 执行指定脚本文件里的命令 |
可以查看sed '' quote.txt
命令加-n参数和不加参数的情况如下
使用-e选项,执行多次删除命令,sed -e '2d;5d' books.txt
脚本文件内容如下,即删除第二行和第五行内容:
执行sed -f testCommand books.txt
命令,结果中删除了第二行和第五行内容,说明命令生效:
sed提供用于控制执行流的循环和分支语句
sed可以根据标签(label)跳转到某一行继续执行;我们可以定义如下标签:
:label
:start
:end
:up
定义完标签之后,如果要跳转到指定的标签,使用b命令后跟着标签名;如果忽略标签名,sed将会跳转到sed文件的结尾。
b start -->表示跳转到start标签的位置
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
使用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
命令。
sed中包含有以下两种形式的行寻址:
以上两中方式的语法都相同
[address]command
sed -n '3d' books.txt
,指定第三行执行d
命令sed -n '2,5 p' books.txt
,第二行到第五行执行p
命令M,+n
,选定第M行开始的下n行M~n
,选定M行开始的每n行sed编辑器执行基础命令时,会基于换行符的位置将数据分成多行,一次处理一行的数据,然后移到下一行重复这个过程。
但是sed编辑器也有用来处理多行文本的特殊命令
命令 | 说明 |
---|---|
N | 将数据流中的下一行追加进来组成多行组一起处理 |
P | 输出多行文本的模式空间中的第一行 |
sed中含有两个可以用作命令的特殊字符:= 和**&**
=
命令用于输出行号
sed -n '$n' books2.txt
,输出最后一行的行号:
字符 | 说明 |
---|---|
^ | 匹配行的开头 |
$ | 匹配行的结尾 |
sed '/Coelho$/ p' books2.txt
字符 | 说明 |
---|---|
. | 匹配除了换行符以外的所有单个字符 |
$ echo -e 'cat\ndog\nmat\nrats' | sed -n '/..t$/ p'
cat
mat
符号 | 说明 |
---|---|
[] | 匹配字符集 |
[^] | 排除字符集 |
[-] | 匹配字符范围 |
字符 | 说明 |
---|---|
? | 匹配0次到1次 |
+ | 匹配一次到多次 |
* | 匹配0次到多次 |
{n} | 精确匹配n次 |
{n,} | 至少匹配n次 |
{n,m} | 匹配n-m次 |
字符 | 说明 |
---|---|
\s | 匹配单个空白内容 |
\S | 匹配单个非空白内容 |
\w | 匹配单个单词 |
\W | 匹配非单词 |