linux下sed的使用(上)
本文介绍sed的使用,其中主要包括sed文本处理、sed文本块处理、sed的导入和导出。
sed简介:sed全称是Stream EDdit ,即流编辑器。他的特点如下:
--非交互,基于模式匹配的过滤及修改文本;
--逐行处理,并将结果输出到屏幕上;
--可实现对文本的输出、删除、替换、复制、剪切、导入、导出等各种操作;
--他有两个空间,模式空间和保持空间,主要在导入导出的时候着重讲解。
下面进入正文:
一、sed文本处理:
1、sed命令的基本用法
1)命令格式说明
格式1:前置命令 | sed [选项] '编辑指令'
格式2:sed [选项] '编辑指令' 文件.. ..
相关说明如下:
其中,“编辑指令”用来实现过滤操作,由“[定址符]处理动作”组成;
而“定址符”用来定义需要操作的文本,由“[地址1,[地址2]]组成,地址1为起始位置,地址2为结束位置;
未指定“定址符”时,默认处理所有文本;
只指定地址1时,只处理与地址1相匹配的文本。
sed常见命令选项:
-n :屏蔽输出源数据
-i:直接对源文件进行操作
-f:使用sed脚本,对文件进行处理
-r:去掉正则表达式的转义符号和其他选项一起使用时放在首位
或者用转义符号 '\'
-e:指定多个处理动作,多个处理动作之间用分号;间隔
-p:打印输出
-d:删除
{}:可徐和多个命令组,以分号间隔
2)sed命令的 -n 选项
执行p打印等过滤操作时,希望看到的是符合条件的文本。但不使用任何选项时,默认会将原始文本一并输出,从而干扰过滤效果。比如,尝试用sed输出/etc/rc.local的第1行:
[root@localhost ~]# sed '1p' /etc/rc.local
#!/bin/sh
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.
touch /var/lock/subsys/local
可以发现所有的行都被显示出来了。―― 正确的用法应该添加 -n 选项,这样就可以只显示第2行了:
[root@svr5 ~]# sed -n '1p' /etc/rc.local
#!/bin/sh
而在执行d删除等过滤操作时,希望看到的是删除符合条件的文本之后还能够被保留下来的文本,所以这时候就不应该使用 -n 选项了。比如,删除/etc/rc.local文件的第1-4行文本:
[root@localhost ~]# sed '1,4d' /etc/rc.local
# want to do the full Sys V style init stuff.
touch /var/lock/subsys/local
3)sed命令的 -i 选项
正常情况下,sed命令所做的处理只是把操作结果(包括打印、删除等)输出到当前终端屏幕,而并不会对原始文件做任何更改:
[root@svr5 ~]# cp /etc/rc.local rclocal.txt //复制为新文件,用作测试
[root@svr5 ~]# cat rclocal.txt //确认测试文件内容
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.
touch /var/lock/subsys/local
[root@svr5 ~]# sed '1,4d' rclocal.txt //删除第1~4行,输出结果
# want to do the full Sys V style init stuff.
touch /var/lock/subsys/local
[root@svr5 ~]# cat rclocal.txt //查看原始文本,并未改动
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.
touch /var/lock/subsys/local
若希望直接修改文件内容,应添加选项 -i 。
比如,直接删除rcloal.txt文件的第1~4行,不输出结果:
[root@svr5 ~]# sed -i '1,4d' rclocal.txt //删除操作
[root@svr5 ~]# cat rclocal.txt //确认删除结果
# want to do the full Sys V style init stuff.
touch /var/lock/subsys/local
下文中关于使用sed修改文件的示例中,为了避免大家在练习过程中因误操作导致系统故障,部分命令省略 �Ci 选项,不再逐一说明。需要时,大家可自行加上此选项。
4)sed命令的 -e 选项
选项 -e 用来指定一条“编辑指令”,实际上 -e 通常是被省略了;当需要执行多条编辑指令时,可添加多组 -e 操作。比如,输入/etc/rc.local文件的第1行、第4行,可以采用这种方式:
[root@svr5 ~]# sed -n -e '1p' -e '4p' /etc/rc.local
#!/bin/sh
# You can put your own initialization stuff in here if you don't
如果不使用 -e ,也可以用分号来隔离多个操作(如果有定址条件,则应该使用{ }括起来),比如:
[root@svr5 ~]# sed -n '1p;4p' /etc/rc.local
#!/bin/sh
# You can put your own initialization stuff in here if you don't
或者:
[root@svr5 ~]# sed -n '{1p;4p}' /etc/rc.local
#!/bin/sh
# You can put your own initialization stuff in here if you don't
2.使用sed过滤文本
先创建一个练习用的测试文件,每一行之前添加行号,方便练习时查看效果:
[root@svr5 ~]# cat -n /etc/rc.local > rclocal.txt
[root@svr5 ~]# cat rclocal.txt
1 #!/bin/sh
2 #
3 # This script will be executed *after* all the other init scripts.
4 # You can put your own initialization stuff in here if you don't
5 # want to do the full Sys V style init stuff.
6
7 touch /var/lock/subsys/local
1)输出所有行,相当于cat命令。
[root@svr5 ~]# sed -n 'p' rclocal.txt
1 #!/bin/sh
2 #
3 # This script will be executed *after* all the other init scripts.
4 # You can put your own initialization stuff in here if you don't
5 # want to do the full Sys V style init stuff.
6
7 touch /var/lock/subsys/local
2)输出第4行。
[root@svr5 ~]# sed -n '4p' rclocal.txt
4 # You can put your own initialization stuff in here if you don't
3)输出第4~7行。
[root@svr5 ~]# sed -n '4,7p' rclocal.txt
4 # You can put your own initialization stuff in here if you don't
5 # want to do the full Sys V style init stuff.
6
7 touch /var/lock/subsys/local
4)输出第4行和第7行。
[root@svr5 ~]# sed -n '4p;7p' rclocal.txt
4 # You can put your own initialization stuff in here if you don't
7 touch /var/lock/subsys/local
5)输出第2行及之后的3行。
[root@svr5 ~]# sed -n '2,+3p' rclocal.txt
2 #
3 # This script will be executed *after* all the other init scripts.
4 # You can put your own initialization stuff in here if you don't
5 # want to do the full Sys V style init stuff.
6)输出以local结尾的行。
[root@svr5 ~]# sed -n '/local$/p' rclocal.txt
7 touch /var/lock/subsys/local
7)输出奇数行。
[root@svr5 ~]# sed -n 'p;n' rclocal.txt
1 #!/bin/sh
3 # This script will be executed *after* all the other init scripts.
5 # want to do the full Sys V style init stuff.
7 touch /var/lock/subsys/local
或者用 #sed -n '1~2p' rclocal.txt
8)输出偶数行。
[root@svr5 ~]# sed -n 'n;p' rclocal.txt
2 #
4 # You can put your own initialization stuff in here if you don't
6
或者用 #sed -n '2~2p' rclocal.txt
~(飘号):满几行输出多少行:比如1~2满2行输出第1行,2~2满2行输出第2行
9)从第5行输出到最后一行。
[root@svr5 ~]# sed -n '5,$p' rclocal.txt
5 # want to do the full Sys V style init stuff.
6
7 touch /var/lock/subsys/local
10)输出文本的行数。
[root@svr5 ~]# sed -n '$=' rclocal.txt
7
3.使用sed删除文本.
还以rclocal.txt文件为例,文件内容如下所示:
[root@svr5 ~]# cat rclocal.txt
1 #!/bin/sh
.2 #
3 # This script will be executed *after* all the other init scripts.
4 # You can put your own initialization stuff in here if you don't
5 # want to do the full Sys V style init stuff.
6
7 touch /var/lock/subsys/local
1)删除第第3~5行文本
[root@svr5 ~]# sed '3,5d' rclocal.txt
1 #!/bin/sh
2 #
6
7 touch /var/lock/subsys/local
2)删除所有包含“init”的行。
[root@svr5 ~]# sed '/init/d' rclocal.txt
1 #!/bin/sh
2 #
6
7 touch /var/lock/subsys/local
3)删除所有包含“init”的行、所有包含“bin”的行。
[root@svr5 ~]# sed '/init/d;/bin/d' rclocal.txt
2 #
6
7 touch /var/lock/subsys/local
4)删除不包括“init”的行。
[root@svr5 ~]# sed '/init/!d' rclocal.txt
3 # This script will be executed *after* all the other init scripts.
4 # You can put your own initialization stuff in here if you don't
5 # want to do the full Sys V style init stuff.
这个实际效果相当于只显示包含“init”的行:
6)删除文件中的空行
# sed '/^$/d' rclocal.txt //删除所有空行:
手动添加2行空行到测试文件;
清理重复空行,若连续两个空行只保留一个:
# sed '/^$/{n;/^$/d}' rclocal.txt
4.使用sed实现字符串替换
-s:替换(跟vim vi编辑的时候的替换本质是一样的,)
把文件中每一行里的符号删除,用替换!替换为空即为删除!
格式:
sed -i ‘【定址符】s/源数据/新数据/【选项】’ 文件列表
或者
命令 | sed ‘【定址符】s/源数据/新数据/【选项】’
多个文件列表之间用“空格”间隔
常用选项:-rn
定址符:可选项,不指定逐行处理数据,可以使用正则表达式或行号
源字符:被替换的字符,可以用正则表达式匹配
新字符:替换后的字符
选项:g 全局替换 默认只替换第一个匹配的(global)
i忽略字母大小写匹配
() 保存被匹配的字符,用他实现后向引用,最多可以使用9个模
式,模式中最左边的标签是第一个,后向引用的时候用\1表示
& 保存查找串以便在替换串中引用
*******************注意()的使用↑*********************************
************************正则表达式的使用↓**************************
定址符正则的使用:
sed ‘/[01]/s/bash/nologin/g’ a.txt把包含数字1和0的行中的bash换成nologin
当要替换的符号和间隔符号“/“重的时候可以自己替换间隔符号
sed -r '1,10s;/sbin/nologin;/bin/bash;' sed.txt
示例:还是以rclocal.txt文件为例
1)将所有行中的第一个“ll”(如果有的话)替换为“TARENA”。
[root@svr5 ~]# sed 's/ll/TARENA/' rclocal.txt
1 #!/bin/sh
2 #
3 # This script wiTARENA be executed *after* all the other init scripts.
4 # You can put your own initialization stuff in here if you don't
5 # want to do the fuTARENA Sys V style init stuff.
6
7 touch /var/lock/subsys/local
2)将所有的“ll”(如果有的话)替换为“TARENA”。
[root@svr5 ~]# sed 's/ll/TARENA/g' rclocal.txt
1 #!/bin/sh
2 #
3 # This script wiTARENA be executed *after* aTARENA the other init scripts.
4 # You can put your own initialization stuff in here if you don't
5 # want to do the fuTARENA Sys V style init stuff.
6
7 touch /var/lock/subsys/local
3)将第3行内的第2个“script”替换为“SCRIPT”。
[root@svr5 ~]# sed '3s/script/SCRIPT/2' rclocal.txt
1 #!/bin/sh
2 #
3 # This script will be executed *after* all the other init SCRIPTs.
4 # You can put your own initialization stuff in here if you don't
5 # want to do the full Sys V style init stuff.
6
7 touch /var/lock/subsys/local
*******s/源/目标/[选项] 这里的选项可以是g全局,也可以什么都不加,不加的时候默认替换第一个,也可以是数字N,数字的时候表示替换匹配的第N个******
4)删除文件内指定的字符串(替换为空)。
删除所有的“init”字符串:
[root@svr5 ~]# sed 's/init//g' rclocal.txt
1 #!/bin/sh
2 #
3 # This script will be executed *after* all the other scripts.
4 # You can put your own ialization stuff in here if you don't
5 # want to do the full Sys V style stuff.
6
7 touch /var/lock/subsys/local
删除所有的“script”、所有的“stuff”、所有的字母e,或者的关系用转义方式 \| 来表示:
[root@svr5 ~]# sed 's/script\|stuff\|e//g' rclocal.txt
.1 #!/bin/sh
2 #
3 # This will b xcutd *aftr* all th othr init s.
4 # You can put your own initialization in hr if you don't
5 # want to do th full Sys V styl init .
6
7 touch /var/lock/subsys/local
5)配置行的注释、解除注释。
解除/etc/rc.local文件第3~5行的注释(去掉开头的 # ):
[root@svr5 ~]# sed '3,5s/^#//' /etc/rc.local
#!/bin/sh
#
This script will be executed *after* all the other init scripts.
You can put your own initialization stuff in here if you don't
want to do the full Sys V style init stuff.
touch /var/lock/subsys/local
去掉所有注释(行首去掉#):
[root@svr5 ~]# sed 's/^//' /etc/rc.local
把开头替换为空,即去掉所有注释;其实在vi vim 编辑器里也可以这么用
将/etc/rc.local文件的第6~7行注释掉(行首添加 # ):
[root@svr5 ~]# sed '6,7s/^/#/' /etc/rc.local
6)小括号的应用
修改IP地址的网段部分,主机地址不变。
直接修改网卡eth0的配置文件,检查原有的配置内容:
[root@svr5 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
# Intel Corporation 82545EM Gigabit Ethernet Controller (Copper)
DEVICE=eth0
BOOTPROTO=none
HWADDR=00:0c:29:82:09:e9
ONBOOT=yes
NETMASK=255.255.255.0
IPADDR=192.168.4.4
TYPE=Ethernet
若希望将IP地址192.168.4.4修改为172.16.16.4,则应该定位到“IPADDR”所在的行,执行相应的替换(仅测试,尚未修改):
[root@svr5 ~]# sed '/^IPADDR/s/192.168.4.4/172.16.16.4/' \
/etc/sysconfig/network-scripts/ifcfg-eth0 | grep "^IPADDR"
IPADDR=172.16.16.4
由于要求只修改网段地址,当上述操作在脚本中使用时,若要提供给不同的主机运行,显示不能直接写成 4 。这种情况下,可以利用扩展正则表达式的 \1、\2、……等调用,分别对应此前第1个、第2个、…… 以 ()包围的表达式所匹配的内容。
所以上述操作可以改为如下(启用扩展匹配应添加 -r 选项):
[root@svr5 ~]# sed -r -i '/^IPADDR/s/192.168.4.(.*)/172.16.16.\1/' \
/etc/sysconfig/network-scripts/ifcfg-eth0
遗忘回顾:
1、选项:-r:去掉正则表达式的转义符号和其他选项一起使用时放在首位
或者加转义符号 \
-e:指定多个处理动作,多个处理动作之间用分号;间隔
2、在替换的时候 s/源/目标/[选项] 这里的选项可以是g全局,也可以什么都不加,不加的时候默认替换第一个,也可以是数字N,数字的时候表示替换匹配的第N个
3、s替换可以参考s替换在vi vim编辑器中的用法,触类旁通
4、