sed处理时,有2个缓冲区:【pattern space】和【hold space】
sed执行过程:
先读入一行,去掉尾部换行符,存入【pattern space】,执行编辑命令。 处理完毕,除非加了-n参数,把现在的【pattern space】打印出来,在后边打印曾去掉的换行符。 把【pattern space】置空。 接着读下一行,处理下一行。
sed的默认输出:【pattern space】里的内容输出到标准输出。
常用选项:
-
【pattern space】里的内容不输出到标准输出:-n
-
默认只能执行一个脚本,执行多个脚本:-e script, --expression=script
可以有多个-e script
-
如果要执行的脚本特别多,可以指定一个脚本文件:-f /path/to/sed_scirpt
脚本文件里,每行一个编辑命令。
-
支持使用扩展的正则表达式,默认是基本正则表达式:-r
-
直接编辑原文件:-i
地址定界:
1,不给地址:对全文进行处理
2,单地址
- #:指定行
- /pattern/:被此模式所匹配到的每一行
3,地址范围
-
$:最后一行
-
#,#:起始和结束
-
#,+#:起始,和从起始加多少行
-
#,/pat1/:起始到,pat1匹配到的行
-
/pat1/,/pat2/:pat1匹配到的行,到pat2匹配到的行
4,步进:~
- 1~2:1,3,5,7,9.。。行(所有奇数行)
- 2~2:2,4,6,8,10.。。行(所有偶数行)
编辑命令:
如果有多个命令,则用分号分隔。
-
删掉【pattern space】里的内容:d
删除/etc/fstab的第一行到第五行。
# sed '1,5d' /etc/fstab
-
打印【pattern space】里的内容:p
乍一看是打印奇数行,但实际是把偶数行打印了出来,而且奇数行打印了2遍。 # sed '1~2p' /etc/fstab 使用-n禁止sed的默认行为后,就是打印奇数行了 # sed -n '1~2p' /etc/fstab
-
在行前插入:-i \text 支持使用\n实现多行插入
# sed '3a \new line\nother line' /etc/fstab # # /etc/fstab new line other line 在UUID行前加一段注释: # sed '/^UUID/i \#this is base for UUID' /etc/fstab #this is base for UUID UUID=3d3b316a-529e-484a-9895-e785fdde5365 /boot xfs defaults 0 0
-
在行后插入:-a \text 支持使用\n实现多行插入
# sed '3i \new line\nother line' /etc/fstab # new line other line # /etc/fstab
-
替换行:-c \text 把匹配到的行,替换成text
把以UUID开头的行,整行替换成text。
# sed '/^UUID/c \#this is base for UUID' /etc/fstab
-
保存匹配到的行,到指定文件中:-w /path/to/save
把不以#号开头的行,保持到/tmp/fsnew
# sed -n '/^[^#]/w /tmp/fsnew' /etc/fstab
-
把指定文件中的内容插入到匹配行的后面:-r /path/to/insert
在/etc/fstab的第三行的后面,插入/tmp/tst的内容。
# cat /tmp/tst aaa bbb [root@localhost ~]# sed '3r /tmp/tst' /etc/fstab # # /etc/fstab aaa bbb
-
在匹配到的行的上一行,加上行号:=
在以UUID开头的行的上一行加上行号
# sed '/^UUID/=' /etc/fstab # # /etc/fstab # Created by anaconda on Fri Nov 29 16:44:28 2019 # # Accessible filesystems, by reference, are maintained under '/dev/disk' # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info # /dev/mapper/centos-root / xfs defaults 0 0 10 UUID=3d3b316a-529e-484a-9895-e785fdde5365 /boot xfs defaults 0 0
-
匹配到的行不执行后面的命令;没匹配到的行执行后面的命令:!。注意:!处理命令之前。
删除不以#开头的行:
# sed '/^#/!d' /etc/fstab # # /etc/fstab # Created by anaconda on Fri Nov 29 16:44:28 2019 # # Accessible filesystems, by reference, are maintained under '/dev/disk' # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info #
-
查找替换:s/要替换的/替换成的/替换标记。它的分隔符/可以自己指定,常用的有s@@@,s###
替换标记:
- 全局替换:g
- 将替换成功的结果保存到文件:w /path/to/save
- 显示替换成功的行:p
练习
1,删除test文件中所有以空白字符开头的行的行首的所有空白字符
# cat test
11
222
333
\+:匹配前面的次数为大于等于1
# sed 's@^[[:space:]]\+@@' test
11
222
333
# sed -n 's@^[[:space:]]\+@@p' test
11
333
2,删除/etc/fstab文件中所有以#开头的行的行首的#号及#后面所有空白字符
# sed 's@^#[[:space:]]*@@' /etc/fstab
3,删除/etc/fstab文件中所有以#开头的行的行首的#号及#后面所有空白字符,和删除所有以UUID开头的行
# sed -e 's@^#[[:space:]]*@@' -e '/^UUID/d' /etc/fstab
4,输出一个绝对路径给sed命令,取出其目录部分,其行为类似dirname
message后面如果有/就匹配不成功了。
# echo "/var/log/messages" | sed 's@[^/]\+$@@'
/var/log/
message后面即使有/也能匹配:非/
[^/]:非/
\+:至少一个
/\?:/有0个或者1个
# echo "/var/log/messages/" | sed 's@[^/]\+/\?$@@'
/var/log/
message后面即使有/也能匹配
由于使用了-r(扩展正则表达式),+和?前面的\可以省略了。
# echo "/var/log/messages/" | sed -r 's@[^/]+/?$@@'
/var/log/
[root@localhost ~]#
高级编辑命令
- 把【pattern space】空间中的内容覆盖到【hold space】空间:h
- 把【pattern space】空间中的内容追加到【hold space】空间,然后删除【pattern space】空间中的内容:H
- 把【hold space】空间中的内容覆盖到【pattern space】空间:g
- 把【hold space】空间中的内容追加到【pattern space】空间,然后删除【hold space】空间中的内容:G
- 互换【hold space】【pattern space】里的内容:x
- 把匹配到的行的下一行放入【pattern space】,并把匹配到的行删除掉:n
- 把匹配到的行的下一行放入【pattern space】,不删除匹配到的行:N
- 删除【pattern space】空间中的行:d
- 删除多行模式下【pattern space】里的所有行。(比如用N了,【pattern space】里就有多行):D
1,显示偶数行:
执行过程:先把第一行读入到了【pattern space】,后面的命令的n。n的意思是读下一行,并删除当前【pattern space】里的内容后,再把下一行的内容放入【pattern space】;接下来的命令是p,p就是把当前【pattern space】里的内容输出到标准输出,所有第二行就打印到了标准输出了。然后读第3行,后面的命令是n,就再读一行,以此类推。
# sed -n 'n;p' /etc/fstab
2,倒置文本:
参看:https://blog.csdn.net/itsenlin/article/details/21129405
执行过程:先把第一行读入到了【pattern space】,发现第一行的命令是1!G,所以不做处理;接着是h,则把【pattern space】的内容,覆盖到【hold space】;接着是命令$!d,因为不是最后一行,所以执行d命令,删除【pattern space】里的内容。
读第二行到【pattern space】,发现命令是1!G,由于不是第1行了,所以执行G命令,把hold space】的内容追加到了【pattern space】,这时【pattern space】里放的是第二行和第一行的内容,而且第二行在第一行的前面。接着是$!d,由于不是最后一行,所以执行d命令,删除【pattern space】里的内容。
# cat test
11
222
333
最后一行,没有执行d,而且【pattern space】里的内容,而且没有使用-n,所以就把倒叙打印到标准输出了。
# sed '1!G;h;$!d' ./test
333
222
11
也可以用下面的命令,实现倒置。
由于没有使用d命令,所以【pattern space】里一直有内容,所以就必须用-n,最后一次用p命令把【pattern space】里的内容输出到标准输出。
# sed -n '1!G;h;$p' test
3,取出最后一行:
# sed '$!d' /etc/fstab
4,取出最后二行:
# sed '$!N;$!D' test
5,删除原有的所有空白行,而后为所有的非空白行添加一个空白行
# cat test
11
空行
空行
222
空行
空行
333
444
555
666
# sed '/^$/d;G' test
11
空行
222
空行
333
空行
444
空行
555
空行
666
空行
6,显示奇数行
# sed 'n;d' /etc/fstab
7,在每一行后面添加一个空白行
# sed 'G' /etc/fstab
8,练习H和g的用法:
# cat t2
one
two
three
# sed 'H;g' t2
一个空行
one
一个空行
one
two
一个空行
one
two
three
图解:H是往hold space里追加,hold space里,其实是有一个换行的。所以第一次把one加到hold space后,one的前一行就是空行。
# c/c++ 学习互助QQ群:877684253 ![](https://www.icode9.com/i/l/?n=18&i=blog/1414315/201811/1414315-20181106214320230-961379709.jpg) # 本人微信:xiaoshitou5854