2015-08-29 创建
1、概述
sed 是一种在线编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有 改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。
2、命令格式
sed [OPTION]... {script-only-if-no-other-script} [input-file]...
或者可以理解为:sed [options] 'AddressCommand' file ...
Address:
0、first~step
删除first,每次步长step都删除
1、StartLine,EndLine
比如1,100
$:最后一行
2、/RegExp/
/root/
3、/pattern1/,/pattern2/
第一次被pattern1匹配到的行开始,至第一次被pattern2匹配到的行结束,这中间的所有行
4、LineNumber
指定的行
5、StartLine, +N
从startLine开始,向后的N行;
Command:
d: 删除符合条件的行;
p: 显示符合条件的行;
a \string: 在指定的行后面追加新行,内容为string # 新行
\n:可以用于换行
i \string: 在指定的行前面添加新行,内容为string # 新行
r FILE: 将指定的文件的内容添加至符合条件的行处
w FILE: 将地址指定的范围内的行另存至指定的文件中;
s/pattern/string/ 默认只替换每行中第一次被模式匹配到的字符串
【pattern 代表可以使用正则表达式】
加修饰符
g: 全局替换 s/pattern/string/g【修饰符】
i: 忽略字符大小写 s/pattern/string/i【修饰符】
s///: s###, s@@@ 效果一样
\(\), \1, \2
l..e: like-->liker
love-->lover
like-->Like
love-->Love
& 引用模式匹配整个串
3、常用命令参数
-n, --quiet, --silent 抑制模式空间的自动打印
[oldboy@moban sed]$ cat sed1
qwewq
zhang liang
werwet bbb
ewtew 123
[oldboy@moban sed]$ sed '/bbb/p' sed1 # 打印模式控件内容和匹配内容
qwewq
zhang liang
werwet bbb
werwet bbb # 重复内容
ewtew 123
[oldboy@moban sed]$ sed -n '/bbb/p' sed1 # 不打印模式空间内容,只打印匹配内容
werwet bbb
-e script, --expression=script 将脚本添加到要执行的命令。
允许多点编辑。
[oldboy@moban sed]$ cat sed1
qwewq
wetwdgh
5555
zhang liang
werwet bbb
ewtew 123
ettte
[oldboy@moban sed]$ sed -e '1,3d' sed1
zhang liang
werwet bbb
ewtew 123
ettte
[oldboy@moban sed]$ sed -e '1,3d' -e 's/zhang/bing/' sed1 # 第一个是删除1到3行,第二个是将'zhang'替换为'bing'
bing liang
werwet bbb
ewtew 123
ettte
-f script-file, --file=script-file 添加脚本文件内容到将要执行的命令。示例如下
[oldboy@moban sed]$ cat script1 # 没有引号
1,3d # 删除1到3行
s/zhang/bing/ # 每行中把 zhang 替换为 bing
/liang/p
# 行中出现liang 的打印出来【不能使用 -n /liang/p,或者 n /liang/p。因为这是脚本不支持 命令选项】
[oldboy@moban sed]$ cat sed1
qwewq
wetwdgh
5555
zhang liang
werwet bbb
ewtew 123
ettte
[oldboy@moban sed]$ sed -f ./script1 sed1
bing liang
bing liang
werwet bbb
ewtew 123
ettte
-i[SUFFIX], --in-place[=SUFFIX] 直接修改读取的档案内容,而不是由屏幕输出。
[oldboy@moban sed]$ cat sed1
zhang liang
werwet bbb
[oldboy@moban sed]$ sed -i s/bbb/liangzhuang/g sed1
[oldboy@moban sed]$ cat sed1
zhang liang
werwet liangzhuang
--posix 禁用所有的GNU扩展。
-r, --regexp-extended 在脚本中使用扩展正则表达式。
-s, --separate 把文件视为单独的,而不是作为一个连续的长流。
-u, --unbuffered 从输入文件中加载最小量的数据,并经常刷新输出缓冲区。
如果没有 -e, --expression, -f, 或 --file 选项,然后第一个非选项参数为sed脚本解释。所有余下的参数都是输入文件的名称,如果没有指定的输入文件,则该标准输入被读取。
命令概要
Zero- or One- address commands 0个、1个 地址匹配
= 打印当前行行号【sed -n '3,$ {=;p}' sed1 或者 sed -n '1,${=;p}' sed1 | sed -n '/^[0-9]*$/{N;s/\n/: /p}'】
[oldboy@moban sed]$ cat sed1
qwewq
wetwdgh
5555
zhang liang
werwet wqeqqq
ewtew 123
ettte
[oldboy@moban sed]$ sed -n '3,$p' sed1
5555
zhang liang
werwet wqeqqq
ewtew 123
ettte
[oldboy@moban sed]$ sed -n '3,$=' sed1 # 打印行号
3
4
5
6
7
另外
[oldboy@moban sed]$ sed -n '3,$ {=;p}' sed1
3
5555
4
zhang liang
5
werwet wqeqqq
6
ewtew 123
7
ettte
[oldboy@moban sed]$ sed -n '1,${=;p}' sed1 | sed -n '/^[0-9]*$/{N;s/\n/: /p}'
1: qwewq
2: wetwdgh
3: 5555
4: zhang liang
5: werwet wqeqqq
6: ewtew 123
7: ettte
a \string 在指定的行后面追加新行,内容为string
【\n:可以用于换行】
[oldboy@moban sed]$ cat sed1
qwewq
wetwdgh
5555
zhang liang
werwet wqeqqq
ewtew 123
ettte
[oldboy@moban sed]$ sed '/^e/a \### hello World!' sed1
qwewq
wetwdgh
5555
zhang liang
werwet wqeqqq
ewtew 123
### hello World!
ettte
### hello World!
<pre name="code" class="java">[oldboy@moban sed]$ sed '/^e/a \### hello \nWorld!' sed1 # 添加了 \n
qwewq
wetwdgh
5555
zhang liang
werwet wqeqqq
ewtew 123
### hello
World!
ettte
### hello
World!
i \string 在指定的行前面添加新行,内容为string
[oldboy@moban sed]$ sed '/^e/i \### hello World!' sed1
qwewq
wetwdgh
5555
zhang liang
werwet wqeqqq
### hello World!
ewtew 123
### hello World!
ettte
q [exit-code] 注意:不接受多行 【sed ’2,5 q’ filename 是不正确的】
Q [exit-code] 注意:不接受多行 【sed ’2,5 Q’ filename 是不正确的】
[oldboy@moban sed]$ cat sed1
qwewq
wetwdgh
5555
zhang liang
werwet wqeqqq
ewtew 123
ettte
[oldboy@moban sed]$ sed '4q' sed1 # 打印第4行后退出 【sed '4q12' sed1】
qwewq
wetwdgh
5555
zhang liang
[oldboy@moban sed]$ sed '4Q' sed1 # 到第4行就退出 【sed '4Q12' sed1】
qwewq
wetwdgh
5555
r filename 追加从 filename 中读取的文本
[oldboy@moban sed]$ cat sed1
qwewq
wetwdgh
5555
zhang liang
werwet wqeqqq
ewtew 123
ettte
[oldboy@moban sed]$ cat script1
1,3d
s/zhang/bing/
n /liang/p
[oldboy@moban sed]$ sed '/^e/r script1' sed1
qwewq
wetwdgh
5555
zhang liang
werwet wqeqqq
ewtew 123 # 第一次追加
1,3d
s/zhang/bing/
n /liang/p
ettte # 第二次追加
1,3d
s/zhang/bing/
n /liang/p
R filename 从filename 中读取一行进行追加。每次读取一行内容。
[oldboy@moban sed]$ sed '/^e/R script1' sed1 # 请注意和 r 的区别
qwewq
wetwdgh
5555
zhang liang
werwet wqeqqq
ewtew 123 # 第一次追加
1,3d # filename 的第一行
ettte # 第二次追加
s/zhang/bing/ # filename 的第二行
c \string 替换匹配的行,内容为string
[oldboy@moban sed]$ cat sed1
qwewq
wetwdgh
5555
zhang liang
werwet wqeqqq
ewtew 123
ettte
[oldboy@moban sed]$ sed '2,4 c \### kjkjkjk\nggggg' sed1 # 替换2到4行内容 # \n 换行
qwewq
### kjkjkjk
ggggg
werwet wqeqqq
ewtew 123
ettte
d 删除模式空间内容
[oldboy@moban sed]$ cat sed1
qwewq
wetwdgh
5555
zhang liang
werwet wqeqqq
ewtew 123
ettte
[oldboy@moban sed]$ sed '3,$ d' sed1
qwewq
wetwdgh
h H 将 pattern buffer 追加到 hold buffer 【h 拷贝, H 追加】
g G g 用 hold buffer 的内容拷贝到 pattern buffer 的内容 , 而 G 将 hold buffer 内容追加到 pattern buffer 【g 拷贝, G 追加】
x 将 pattern buffer 放入 hold buffer, 而将 hold buffer 的内容输出 , pattern buffer 的内容变成下一行
l 列出当前行的【全部信息】 小写的【L】
[oldboy@moban sed]$ sed -n '3,5 l' sed1
5555$
zhang liang$
werwet wqeqqq$
l width 列出当前行的全部信息,如果字符长度为 width 时,那么被打断在下一行显示。这是一个GNU扩展。
[oldboy@moban sed]$ sed -n '3,5 l 10' sed1 # 一个空格也会算作一个字符【第10个时被打断,第10个字符在下一行显示】
5555$
zhang lia\
ng$
werwet wq\
eqqq$
n N 读取【n】/追加【N】 下一行的输入到模式空间。
[oldboy@moban sed]$ sed -n '2,5 {n;p}' sed1
5555
werwet wqeqqq
[oldboy@moban sed]$ cat sed1
qwewq
wetwdgh
5555
zhang liang
werwet wqeqqq
ewtew 123
ettte
[oldboy@moban sed]$ sed -n '2,2 {N;p}' sed1 # 这些现象还有些不理解
wetwdgh
5555
[oldboy@moban sed]$ sed -n '2,3 {N;p}' sed1
wetwdgh
5555
[oldboy@moban sed]$ sed -n '2,4 {N;p}' sed1
wetwdgh
5555
zhang liang
werwet wqeqqq
[oldboy@moban sed]$ sed -n '2,5 {N;p}' sed1
wetwdgh
5555
zhang liang
werwet wqeqqq
[oldboy@moban sed]$ sed -n '2,2 {n;p}' sed1 # 这些现象还有些不理解
5555
[oldboy@moban sed]$ sed -n '2,3 {n;p}' sed1
5555
[oldboy@moban sed]$ sed -n '2,4 {n;p}' sed1
5555
werwet wqeqqq
[oldboy@moban sed]$ sed -n '2,5 {n;p}' sed1
5555
werwet wqeqqq
p 打印当前模式空间内容。
P 命令输出 pattern buffer 中第一个换行符之前的内容
w filename 当前模式空间的内容写入到 filename 中。
[oldboy@moban sed]$ ll
total 8
-rw-rw-r-- 1 oldboy oldboy 31 Sep 4 07:40 script1
-rw-rw-r-- 1 oldboy oldboy 64 Sep 14 23:21 sed1
[oldboy@moban sed]$ cat sed1
qwewq
wetwdgh
5555
zhang liang
werwet wqeqqq
ewtew 123
ettte
[oldboy@moban sed]$ sed -n '3,5 w ztest' sed1
[oldboy@moban sed]$ ll
total 12
-rw-rw-r-- 1 oldboy oldboy 31 Sep 4 07:40 script1
-rw-rw-r-- 1 oldboy oldboy 64 Sep 14 23:21 sed1
-rw-rw-r-- 1 oldboy oldboy 34 Sep 14 23:47 ztest
[oldboy@moban sed]$ cat ztest
5555
zhang liang
werwet wqeqqq
W filename 将当前模式空间的第一行写入filename。这是一个GNU扩展。
[oldboy@moban sed]$ sed -n '3,5 W ztest2' sed1 # 不知道这个模式空间的第一行是怎么定义的????
[oldboy@moban sed]$ cat ztest2
5555
zhang liang
werwet wqeqqq
s/regexp/replacement/ 默认只替换每行中第一次被模式匹配到的字符串
【s/pattern/string/ pattern 代表可以使用正则表达式】
加修饰符
g: 全局替换 s/pattern/string/g【修饰符】
i: 忽略字符大小写 s/pattern/string/i【修饰符】
s///: s###, s@@@ 效果一样 【\(\), \1, \2 分组】【& 引用模式匹配整个串】
示例:
[oldboy@moban ~]$ cat /etc/fstab
UUID=67be2fce-cfc2-4e9e-ae0f-47d70d2d4bad /boot ext4 defaults 1 2
tmpfs /dev/shm tmpfs defaults 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
[oldboy@moban ~]$ sed 's@/@##@' /etc/fstab
UUID=67be2fce-cfc2-4e9e-ae0f-47d70d2d4bad ##boot ext4 defaults 1 2
tmpfs ##dev/shm tmpfs defaults 0 0
devpts ##dev/pts devpts gid=5,mode=620 0 0
[oldboy@moban ~]$ sed 's@/@##@g' /etc/fstab
UUID=67be2fce-cfc2-4e9e-ae0f-47d70d2d4bad ##boot ext4 defaults 1 2
tmpfs ##dev##shm tmpfs defaults 0 0
devpts ##dev##pts devpts gid=5,mode=620 0 0
[oldboy@moban ~]$
[oldboy@moban ~]$ sed 's@u@##@g' /etc/fstab
UUID=67be2fce-cfc2-4e9e-ae0f-47d70d2d4bad /boot ext4 defa##lts 1 2
tmpfs /dev/shm tmpfs defa##lts 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
[oldboy@moban ~]$ sed 's@u@##@gi' /etc/fstab
####ID=67be2fce-cfc2-4e9e-ae0f-47d70d2d4bad /boot ext4 defa##lts 1 2
tmpfs /dev/shm tmpfs defa##lts 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
l..e: like-->liker
love-->lover
like-->Like
love-->Love
[oldboy@moban sed]$ cat sed2
hello, like
hi, my love
[oldboy@moban sed]$ sed 's/l..e/l..er/' sed2
hello, l..er
hi, my l..er
[oldboy@moban sed]$ sed 's/l..e/&r/' sed2 # 使用了 &
hello, liker
hi, my lover
[oldboy@moban sed]$ sed 's/\(l..e\)/\1r/' sed2 # 使用了向后引用 或者扩展正则: sed -r 's/(l..e)/\1r/' sed2
hello, liker
hi, my lover
地址
sed 命令可以不给地址,那么命令对所有行有效。如果有了地址,那么匹配的地址行将会执行命令。
关于地址范围要注意的三件事:1、语法是addr1,addr2 (地址是用逗号分隔的);addr1 总是被接受,尽管有 addr2 选择行更靠前一些;如果addr2是正则表达式,那么他不会再次匹配addr1。
数据准备
[oldboy@moban sed]$ cat sed1
qwewq
wetwdgh
5555
zhang liang
werwet wqeqqq
ewtew 123
ettte
支持一下地址类型:
number 支持特定行number 匹配。
[oldboy@moban sed]$ sed -n '4p' sed1
zhang liang
first~step 从first 开始匹配,步长为step ,
其中 first 可以为0。
[oldboy@moban sed]$ sed -n '1~3p' sed1
qwewq
zhang liang
ettte
[oldboy@moban sed]$ sed -n '0~3p' sed1
5555
ewtew 123
$ 匹配最后一行
[oldboy@moban sed]$ sed -n '4,$p' sed1
zhang liang
werwet wqeqqq
ewtew 123
ettte
/regexp/ 根据正则表达式匹配
[oldboy@moban sed]$ sed -n '/^e/p' sed1 # 以 e开头的行匹配
ewtew 123
ettte
\cregexp
c 根据正则表达式匹配,c 可以是任意字符
[oldboy@moban sed]$ sed -n '\Q^eQp' sed1
ewtew 123
ettte
addr1,+N 匹配行 addr1 和接下来的N 行。
[oldboy@moban sed]$ sed -n '3,+2p' sed1
5555
zhang liang
werwet wqeqqq
4、常用示例
一、
# sed "2,4d" /etc/fstab
# sed '3,$d' /etc/fstab // 注意:sed "3,$d" /etc/fstab 【出错】
# sed '2,+3d' /etc/fstab // 删除第二行,和接下来的3行
# sed '3d' /etc/fstab // 删除第三行
# sed '/^\//d' /etc/fstab // 删除以 / 开头的行
二、
# sed '/fs/a \@@@ dgfeeg wert' /etc/fstab
# sed '/fs/a \### hello world.\n@@@ HellO WORLD!!' /etc/fstab // \n 用于换行
# sed '/fs/i \@@@ werwe.\n!!!wer wetwet' /etc/fstab
# sed '2r /etc/issue' /etc/fstab
# sed '2,3r /etc/issue' /etc/fstab
# sed '/fs/w /tmp/fs.txt' /etc/fstab
# sed 's/fs/FSS/' /etc/fstab
# sed 's/^\//#/' /etc/fstab // 表示行首的 / 换位 #
# sed 's/\//@/g' /etc/fstab
# sed 's@/@###@g' /etc/fstab // 把 / 全局替换为 ###
# sed 's/l..e/l..er/' sedtest.txt // 注意结果
# sed 's/l..e/&r/g' sedtest.txt
# sed 's/\(l..e\)/\1r/' sedtest.txt
# sed 's/l\(..e\)/L\1/' sedtest.txt // like-->Like love-->Love
三、
1、删除/etc/grub.conf文件中行首的空白符;
# sed -r 's@^[[:space:]]+@@g' /etc/grub.conf
2、替换/etc/inittab文件中"id:3:initdefault:"一行中的数字为5;
# sed 's@\(id:\)[0-9]\(:initdefault:\)@\15\2@g' /etc/inittab
3、删除/etc/inittab文件中的空白行;
# sed '/^$/d' /etc/inittab
4、删除/etc/inittab文件中开头的#号;
# sed 's@^#@@g' /etc/inittab
5、删除某文件中开头的#号及后面的空白字符,但要求#号后面必须有空白字符;
# sed -r 's@^#[[:space:]]+@@g' /etc/inittab
6、删除某文件中以空白字符后面跟#类的行中的开头的空白字符及#
# sed -r 's@^[[:space:]]+#@@g' /etc/inittab
7、取出一个文件路径的目录名称; 【/etc/rc.d/we/werdg/】 【结果:/etc/rc.d/we/】
echo "/etc/rc.d/" | sed -r 's@^(/.*/)[^/]+/?@\1@g'
解析:^(/.*/) [^/]+【匹配不是 / 的字符,有一个或则多个】 /?【是否以/结尾】
基名: 【/etc/rc.d/we/werdg/】 【结果:werdg】
echo "/etc/rc.d/" | sed -r 's@^/.*/([^/]+)/?@\1@g'
5、命令所在位置和类型
[oldboy@moban sed]$ which sed
/bin/sed
[oldboy@moban sed]$ type sed
sed is hashed (/bin/sed)
6、另请参见