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 的第二行
Commands which accept address ranges 命令可以接受地址范围
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 ### kjkjkjknggggg' 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)/L1/' 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:)@152@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)
原文始发于:Linux sed 命令