NoteDeep
什么是sed?
sed是非交互式的编辑器。它不会修改文件,除非使用shell重定向来保存结果,默认情况下,所有的输出行都被打印到屏幕上。
sed编辑器逐行处理文件(或者输入),并将结果发送到屏幕。
具体过程:首先sed把当前正在处理的行保存在一个临时缓冲区中(也成为模式空间),然后处理临时缓冲区中的行,完成后把该行发送到屏幕上,sed每处理完一行,就将其从临时缓冲区中删除,然后将下一行读入,进行处理和显示,处理完出入文件的最后一行后,sed便结束运行。sed把每一行都存在临时缓冲区中,对这个副本进行编辑,所以不会修改源文件。



什么是定址?
定址用于决定对哪些行进行编辑。地址的形式可以是数字、正则表达式、或者二者结合,如果没有指定地址,sed将处理输入文件的所有行。

地址如果是一个数字,则表示行号
地址如果是"$" ,则表示最后一行。

sed命中有许多符号,表示不同的含义,我们将通过示例来一一演示。首先我们创建一个名为 sedtest的文本文件,其内容如下:
[root@localhost135 ~]# cat sedtest
My name is alice.
Your name is peter.
alice is peter's wife.
peter is alice's husband
[root@localhost135 ~]#
对定址的演示
[root@localhost135 ~]# sed -n '3p' sedtest
alice is peter's wife. #只打印第三行
[root@localhost135 ~]#
[root@localhost135 ~]# sed -n '$p' sedtest
peter is alice's husband #只打印最后一行
[root@localhost135 ~]#

只显示指定行范围的文件内容
[root@localhost135 ~]# sed -n '2,3p' sedtest
Your name is peter.
alice is peter's wife. #只打印第二到第三行的内容,包含 第二第三 行
[root@localhost135 ~]#

地址是逗号分隔的,那么需要处理的地址是这两行之间的范围(包括这两行在内),范围可以用数字、正则表达式、或者二者结合来表示。
[root@localhost135 ~]# sed '2,3d' sedtest #删除第二第三行,只打印出了第一和第四行
My name is alice.
peter is alice's husband
[root@localhost135 ~]# cat -n sedtest #查看原文件,内容仍然是完整的,所以sed不会对原文件产生影响
1 My name is alice.
2 Your name is peter.
3 alice is peter's wife.
4 peter is alice's husband
[root@localhost135 ~]# sed '/My/,/You/d' sedtest #删除包含 "My" 的行到包含"You"的行之间的行
alice is peter's wife.
peter is alice's husband
[root@localhost135 ~]# sed '/My/,3d' sedtest #删除包含"My"的行到第三行的内容
peter is alice's husband
[root@localhost135 ~]#
以上示例中的一些用法,你可能还不太了解是什么意思,不急,下面我们就来总结一下sed命令中的一些选项及对应的功能。


命令与选项
sed命令告诉sed如何处理由地址指定的各输入行,如果没有指定地址,则处理所有的输入行。

首先来看 sed命令
  1. a\ -------- 在当前行后添加一行或多行。多行时除最后一行外,每行末尾需要用 "\" 续行
  2. c\ -------- 用此符号后的新文本替换当前行中的文本。多行时除最后一行外,每行末尾需用 "\" 续行
  3. i\ -------- 在当前行之前插入文本。多行时除最后一行外,每行末尾需用 "\" 续行
  4. d -------- 删除行
  5. h -------- 把模式空间里的内容复制到暂存缓冲区
  6. H -------- 把模式空间里的内容追加到暂存缓冲区
  7. g -------- 把暂存缓冲区里的内容复制到模式空间,覆盖原有的内容
  8. G -------- 把暂存缓冲区里的内容追加到模式空间,追加在原有内容的后面
  9. I -------- 列出非打印字符
  10. p -------- 打印行
  11. n -------- 读入下一输入行,并从下一条命令而不是第一条命令开始对其处理
  12. q -------- 结束或者退出sed
  13. r -------- 从文件中读取输入行
  14. !--------对所选行以外的所有行应用命令
  15. s -------- 用一个字符串替换另一个字符串
  16. w -------- 将所选的行写入文件
  17. x -------- 交换暂存缓冲区与模式空间的内容
  18. y -------- 将字符替换为另一个字符(不能对正则表达式使用y命令)
再来看sed选项
-e -------- 进行多项编辑,即对输入行应用多条sed命令时使用
-n -------- 取消默认的输出
-f -------- 指定sed脚本的文件名

退出状态
sed不像grep一样,不管是否找到指定的模式,它的退出状态都是0,只有当命令存在语法错误时,sed的退出状态才不是0。


正则表达式相关符号
与grep一样,sed也支持特殊元字符,来进行模式查找、替换,不同的是,sed使用的正则表达式是括在斜杠线 "/" 之间的模式
如果要把正则表达式分隔符 "/" 改成另一个字符,只需在这个字符前加一个反斜线 "\" ,在字符后跟上正则表达式,再跟上这个字符即可。

元字符
功能
示例
^
$
.
*
[ ]
[^]

\(..\)

&
\<
\>
x\{m\}
x\{m,n\}
x\{m,\}
锚定行首
锚定行尾
匹配除换行符以外的单个字符
匹配零个或多个前导符号
匹配指定字符组内的任一字符
匹配不在指定字符组内的任一字符

保存已匹配的字符,后续用来引用该字符

保存查找串以便在替换中引用
词首定位符
词尾定位符
连续m个x
至少m个,但不超过n个x
至少m个x
/^my/ 匹配所有以my开头的行
/my$/ 匹配所有以my结尾的行
/m..y/ 匹配包含字母m,后跟两个任意字符,再跟字母y的行
/my*/ 匹配包含字母m,后跟零个或者多个y字母的行
/[Mm]y/ 匹配包含My或my的行
/[^Mm]y/ 匹配包含y,但在y之前的那个字符不是M或者m的行
1,20s/\(you)self/\1r/ 标记元字符之间的模式,并将其保存为书签1,之后可以使用\1来引用它。
最多可以定义9个书签,从左边开始编号,最左边的是第一个。
此列中,对第1到20行进行处理,you被保存为书签1,如果发现youself,则替换为your.
s/my/**&**/ 符号&代表查找串。my将被替换为 **my**
/\<my/ 匹配包含以my开头的单词的行
/my\>/ 匹配包含以my结尾的单词的行
/9\{5\}/ 匹配包含连续5个9的行
/9\{5,7}/ 匹配包含连续5到7个9的行
/9\{5,\}/ 匹配包含至少连续5个9的行


示例演示

p 命令
命令p 用于显示模式空间的内容。默认情况下,sed把输入行打印在屏幕上,选线-n用于取消默认的打印操作。当选项-n和命令p同时出现时,sed可打印选定的内容。
[root@localhost135 ~]# sed '/My/p' sedtest # 在不加-n选项的情况下,默认把所有输入行全都打印出来
My name is alice. # 如果某行匹配模式My,p命令将把该行另外打印一遍
My name is alice.
Your name is peter.
alice is peter's wife.
peter is alice's husband
[root@localhost135 ~]# sed -n '/My/p' sedtest # 添加-n选项,取消sed默认打印,p命令只把匹配模式My的行打印一遍
My name is alice.
[root@localhost135 ~]#

d 命令
命令d用于删除输入行。sed先将输入行从文件复制到模式空间里,然后对该行执行sed命令,最后将模式空间里的内容显示在屏幕上。如果发出的是命令d,当前模式空间里的输入行会被删除,不被显示。
[root@localhost135 ~]# sed '$d' sedtest # 删除最后一行,其他的都被显示
My name is alice.
Your name is peter.
alice is peter's wife.
[root@localhost135 ~]# sed '/My/d' sedtest # 删除包含My的行,其他的都被显示
Your name is peter.
alice is peter's wife.
peter is alice's husband
[root@localhost135 ~]#

s 命令
命令s用于替换字符串。
[root@localhost135 ~]# sed 's/My/You/g' sedtest # 命令末端的g表示在行内进行全局替换,也就是说如果某行多次出现My,所有的My都被替换成You
You name is alice.
Your name is peter.
alice is peter's wife.
peter is alice's husband
[root@localhost135 ~]# sed -n '1,3s/wife.$/WIFF/gp' sedtest # 取消默认输出,处理1到3行里匹配以wife.结尾的行,把行内所有的wife.替换成WIFF,并打印到屏幕上。
alice is peter's WIFF
[root@localhost135 ~]# sed -n 's#peter#tom#gp' sedtest # 紧跟在s命令后的字符就是查找串和替换串之间的字符。默认是正斜杠/,但可以改变
Your name is tom. # 无论什么字符(换行符、反斜线除外),只要紧跟s命令,就成了新的串分隔符。
alice is tom's wife. # 示例中通过#作为分隔符,将peter替换成tom
tom is alice's husband
[root@localhost135 ~]#

e 选项
-e选项是编辑命令,用于sed执行多个编辑任务的情况下,在下一行开始编辑前,所有的编辑动作将应用到模式缓冲区中的行上。
[root@localhost135 ~]# sed -e '1,3d' -e 's/peter/tom/g' sedtest # 选项-e用于多重编辑
tom is alice's husband # 第一重编辑删除1-3行,第二重编辑将剩下的文本中所有出现peter替换成tom
[root@localhost135 ~]# # 是逐行进行编辑(即这两个命令都在模式空间的当前行上执行),所以编辑命令的顺序会影响结果

r 命令
r命令是读命令,sed使用该命令将一个文本文件中的内容加到当前文件的特定位置上。
[root@localhost135 ~]# cat rcmd.txt # 创建了一个名为rcmd.txt的文件,内容只有一个 hello
hello
[root@localhost135 ~]# sed '/is/r rcmd.txt' sedtest # 如果在文件sedtest的某一行匹配到了 is ,就在该行后面读入文件rcmd.txt里的内容
My name is alice. # 如果出现 is 的不止一行,则在出现 is 的各行后都读入rcmd.txt文件的内容
hello
Your name is peter.
hello
alice is peter's wife.
hello
peter is alice's husband
hello
[root@localhost135 ~]# # 示例中四行都有 is ,所以插入了四个hello

a\ 命令
a\命令是追加命令,即将需要添加的新文本追加到文件中当前行(即读入模式缓冲区中的行)的后面。所追加的文本行位于sed命令的下方,另起一行。如果要追加的内容超过一行,则每一行都必须以反斜线\结束,最后一行除外。最后一行将以单引号和文件名结束。
[root@localhost135 ~]# sed '/^peter/a\peter and alice are husband and wife' sedtest # 不换行追加
My name is alice.
Your name is peter.
alice is peter's wife.
peter is alice's husband
peter and alice are husband and wife # 追加的内容
[root@localhost135 ~]# sed '/^peter/a\ # 多行追加
> peter and alice are husband\
> and wife' sedtest
My name is alice.
Your name is peter.
alice is peter's wife.
peter is alice's husband
peter and alice are husband
and wife # 追加的内容
[root@localhost135 ~]#

i\ 命令
i\命令是在当前行的前面插入新的文本
[root@localhost135 ~]# sed '/^peter/i hello hello' sedtest # 在以peter开头的行的前面插入 hello hello
My name is alice.
Your name is peter.
alice is peter's wife.
hello hello
peter is alice's husband
[root@localhost135 ~]#

c\ 命令
sed使用该命令将已有的文本修改成新的文本。
[root@localhost135 ~]# sed '/^peter/c\this is test' sedtest # 将以peter开头的行修改成 this is test
My name is alice.
Your name is peter.
alice is peter's wife.
this is test
[root@localhost135 ~]#

n 命令
sed使用该命令获取输入文件的下一行,并将其读入到模式缓冲区中,任何sed命令都将应用到匹配行紧接着的下一行上。

y 命令
字符按照一对一的方式从左到右进行转换。例如,y/abc/ABC/ 将把所有的小写a转换成大写 A,小写b转换成大写B,小写c 转换成大写C
[root@localhost135 ~]# sed 'y/name/NAME/' sedtest # 将所有的小写 name 转换成大写 NAME
My NAME is AlicE.
Your NAME is pEtEr.
AlicE is pEtEr's wifE.
pEtEr is AlicE's husbANd
[root@localhost135 ~]#

h/H 命令和 g/G 命令
[root@localhost135 ~]# sed -e '/peter/h' -e '$G' sedtest
My name is alice.
Your name is peter.
alice is peter's wife.
peter is alice's husband
peter is alice's husband
[root@localhost135 ~]# sed -e '/peter/H' -e '$G' sedtest
My name is alice.
Your name is peter.
alice is peter's wife.
peter is alice's husband

Your name is peter.
alice is peter's wife.
peter is alice's husband
sed -e '/peter/h' -e '$G' sedtest
sed -e '/peter/H' -e '$G' sedtest
# 通过以上两条命令,我们会发现,h会把原来暂存缓冲区的内容清除,只保存最近一次执行h时保存进模式空间的内容。
# H 命令则把每次匹配peter的行,都追加保存在了暂存缓冲区。
[root@localhost135 ~]# sed -e '/peter/H' -e '$g' sedtest
My name is alice.
Your name is peter.
alice is peter's wife.

Your name is peter.
alice is peter's wife.
peter is alice's husband
[root@localhost135 ~]# sed -e '/peter/H' -e '$G' sedtest
My name is alice.
Your name is peter.
alice is peter's wife.
peter is alice's husband

Your name is peter.
alice is peter's wife.
peter is alice's husband
[root@localhost135 ~]#
sed -e '/peter/H' -e '$g' sedtest
sed -e '/peter/H' -e '$G' sedtest
# 通过上面两条命令,我们会发现,g把暂存缓冲区中的内容替换掉了空间模式中当前行的内容,此处即替换了最后一行。
# G命令则把暂存缓冲区的内容追加到了模式空间的当前行后,此处即追加到了末尾。


sed 脚本
sed脚本就是写在文件中的一列sed命令。脚本中,要求命令的末尾不能有任何多余的空格或文本,如果在一行中有多个命令,要用分号分隔,执行脚本时,sed先将输入文件中第一行复制到模式缓冲区,然后对其执行脚本中所有的命令,每一行处理完毕后,sed再复制文件中下一行到模式缓冲区,对其执行脚本中所有命令。使用sed脚本时,不再用引号来确保sed命令不被shell解释。
[root@localhost135 ~]# cat sedtest.bash # 创建了一个名为sedtest.bash的脚本文件
#!/bin/bash
3i\
*****************
3,$s/\(peter\) is \(alice\)/\2 is \1/
$a\
We will love forever !!
[root@localhost135 ~]# sed -f sedtest.bash sedtest # 将此脚本文件应用到sedtest文本文件
My name is alice.
Your name is peter.
*****************
alice is peter's wife.
alice is peter's husband
We will love forever !!
[root@localhost135 ~]#



评论列表