linux下sed的使用(上)

linux下sed的使用(上)

 介绍sed的使用,其中主要包括sed文本处理、文本块处理、sed的导入和导出。

简介:

  sed全称是Stream EDdit,即流编辑器。他的特点如下:

--非交互,基于模式匹配的过滤及修改文本;

--逐行处理,并将结果输出到屏幕上;

--可实现对文本的输出、删除、替换、复制、剪切、导入、导出等各种操作;

--他有两个空间,模式空间和保持空间,主要在导入导出的时候着重讲解。

sed文本处理:

一、sed命令的基本用法

1)命令格式

格式1:前置命令 | sed [选项] '编辑指令'

格式2:sed [选项] '编辑指令' 文件.. ..

编辑指令说明如下:

  1. 其中,“编辑指令”用来实现过滤操作,由“[定址符]+处理动作”组成;

  2. 而“定址符”用来定义需要操作的文本,由“[地址1,[地址2]]组成,地址1为起始位置,地址2为结束位置;

  3. 未指定“定址符”时,默认处理所有文本;

  4. 只指定地址1时,只处理与地址1相匹配的文本。

二、sed常用选项解释:

1
2
3
4
5
6
7
8
9
-n :屏蔽输出源数据
-i:直接对源文件进行操作
-f:使用sed脚本,对文件进行处理
-r:去掉正则表达式的转义符号和其他选项一起使用时放在首位
    或者用转义符号 '\'
-e:指定多个处理动作,多个处理动作之间用分号;间隔
-p:打印输出
-d:删除
{}:可徐和多个命令组,以分号间隔

各选项使用示例:

1."-n"选项

  执行p打印等过滤操作时,希望看到的是符合条件的文本。但不使用任何选项时,默认会将原始文本一并输出,从而干扰过滤效果。比如,尝试用sed输出/etc/rc.local的第1行,可以发现所有的行都被显示出来了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
root@tbj:~# sed '1p' /etc/rc.local
#!/bin/sh -e
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
 
exit 0

  正确的用法应该添加"-n"选项,这样就可以只显示第1行了:

1
2
root@tbj:~# sed -n '1p' /etc/rc.local
#!/bin/sh -e

  而在执行删除等过滤操作时,希望看到的是删除符合条件的文本之后还能够被保留下来的文本,所以这时候就不应该使用"-n"选项了。比如,删除/etc/rc.local文件的第1-4行文本:

1
2
3
4
5
6
7
8
9
10
11
root@tbj:~# sed '1,4d' /etc/rc.local
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
 
exit 0

2."-i"选项

  正常情况下,sed命令所做的处理只是把操作结果(包括打印、删除等)输出到当前终端屏幕,而并不会对原始文件做任何更改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[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行,不输出结果:

1
2
3
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

3."-e"选项

  选项"-e"用来指定一条“编辑指令”,实际上 -e 通常是被省略了;当需要执行多条编辑指令时,可添加多组 -e 操作。比如,输入/etc/rc.local文件的第1行、第4行,可以采用这种方式:

1
2
3
[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",也可以用分号来隔离多个操作(如果有定址条件,则应该使用{ }括起来),比如:

1
2
3
[root@svr5 ~]# sed -n '1p;4p' /etc/rc.local
#!/bin/sh
# You can put your own initialization stuff in here if you don't

或者:

1
2
3
[root@svr5 ~]# sed -n '{1p;4p}' /etc/rc.local
#!/bin/sh
# You can put your own initialization stuff in here if you don't

三、使用sed过滤文本示例:

1.先创建一个练习用的测试文件,每一行之前添加行号,方便练习时查看效果:

1
2
3
4
5
6
7
8
9
root@svr5 ~]# cat -n /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.
6
touch /var/lock/subsys/local

1)输出所有行,相当于cat命令。

1
2
3
4
5
6
7
8
[root@svr5 ~]# sed -n 'p' 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.
6
touch /var/lock/subsys/local

2)输出第4行。

1
2
[root@svr5 ~]# sed -n '4p' rclocal.txt
# You can put your own initialization stuff in here if you don't

3)输出第4~7行。

1
2
3
4
5
[root@svr5 ~]# sed -n '4,7p' rclocal.txt
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.
6
touch /var/lock/subsys/local

4)输出第4行和第7行。

1
2
3
[root@svr5 ~]# sed -n '4p;7p' rclocal.txt
# You can put your own initialization stuff in here if you don't
touch /var/lock/subsys/local

5)输出第2行及之后的3行。

1
2
3
4
5
[root@svr5 ~]# sed -n '2,+3p' rclocal.txt
#
# 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.

6)输出以local结尾的行。

1
2
[root@svr5 ~]# sed -n '/local$/p' rclocal.txt
touch /var/lock/subsys/local

7)输出奇数行。

1
2
3
4
5
[root@svr5 ~]# sed -n 'p;n' rclocal.txt
#!/bin/sh
# This script will be executed *after* all the other init scripts.
# want to do the full Sys V style init stuff.
touch /var/lock/subsys/local

 或者用:

1
#sed -n '1~2p' rclocal.txt

8)输出偶数行。

1
2
3
4
[root@svr5 ~]# sed -n 'n;p' rclocal.txt
#
# You can put your own initialization stuff in here if you don't
6

 或者用:

1
#sed -n '2~2p' rclocal.txt

~(飘号):满几行输出多少行:比如1~2满2行输出第1行,2~2满2行输出第2行

9)从第5行输出到最后一行。

1
2
3
4
[root@svr5 ~]# sed -n '5,$p' rclocal.txt
# want to do the full Sys V style init stuff.
6
touch /var/lock/subsys/local

10)输出文本的行数

1
2
[root@svr5 ~]# sed -n '$=' rclocal.txt
7

2.使用sed删除文本.

还以rclocal.txt文件为例,文件内容如下所示:

1
2
3
4
5
6
7
8
[root@svr5 ~]# cat rclocal.txt
#!/bin/sh
.2 #
# 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.
6
touch /var/lock/subsys/local

1)删除第第3~5行文本

1
2
3
4
5
[root@svr5 ~]# sed '3,5d' rclocal.txt
#!/bin/sh
#
6
touch /var/lock/subsys/local

2)删除所有包含“init”的行。

1
2
3
4
5
[root@svr5 ~]# sed '/init/d' rclocal.txt
#!/bin/sh
#
6
touch /var/lock/subsys/local

3)删除所有包含“init”的行、所有包含“bin”的行。

1
2
3
4
[root@svr5 ~]# sed '/init/d;/bin/d' rclocal.txt
#
6
touch /var/lock/subsys/local

4)删除不包括“init”的行。

1
2
3
4
[root@svr5 ~]# sed '/init/!d' rclocal.txt
# 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.

这个实际效果相当于只显示包含“init”的行:

6)删除文件中的空行

1
# sed '/^$/d' rclocal.txt

 手动添加2行空行到测试文件;清理重复空行,若连续两个空行只保留一个:

1
# sed '/^$/{n;/^$/d}' rclocal.txt

3.使用sed实现字符串替换

-s:替换(跟vim vi编辑的时候的替换本质是一样的)

格式:

sed -i ‘【定址符】s/源数据/新数据/【选项】’ 文件列表

或者

命令 | sed ‘【定址符】s/源数据/新数据/【选项】’

 多个文件列表之间用“空格”间隔

定址符:可选项,不指定逐行处理数据,可以使用正则表达式或行号

源字符:被替换的字符,可以用正则表达式匹配

新字符:替换后的字符

选项:g 全局替换 默认只替换第一个匹配的(global)

  定址符正则的使用:

1
2
# sed ‘/[01]/s/bash/nologin/g’ a.txt
//把包含数字1和0的行中的bash换成nologin

当要替换的符号和间隔符号“/“重的时候可以自己替换间隔符号

1
# sed -r '1,10s;/sbin/nologin;/bin/bash;' sed.txt

示例:还是以rclocal.txt文件为例

1)将所有行中的第一个“ll”(如果有的话)替换为“TARENA”。

1
2
3
4
5
6
7
8
[root@svr5 ~]# sed 's/ll/TARENA/' rclocal.txt
#!/bin/sh
#
# This script wiTARENA 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 fuTARENA Sys V style init stuff.
6
touch /var/lock/subsys/local

2)将所有的“ll”(如果有的话)替换为“TARENA”。

1
2
3
4
5
6
7
8
[root@svr5 ~]# sed 's/ll/TARENA/g' rclocal.txt
#!/bin/sh
#
# This script wiTARENA be executed *after* aTARENA the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the fuTARENA Sys V style init stuff.
6
touch /var/lock/subsys/local

3)将第3行内的第2个“script”替换为“SCRIPT”。

1
2
3
4
5
6
7
8
[root@svr5 ~]# sed '3s/script/SCRIPT/2' 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.
6
touch /var/lock/subsys/local

*******s/源/目标/[选项] 这里的选项可以是g全局,也可以什么都不加,不加的时候默认替换第一个,也可以是数字N,数字的时候表示替换匹配的第N个******

4)删除文件内指定的字符串(替换为空)。

删除所有的“init”字符串:

1
2
3
4
5
6
7
8
[root@svr5 ~]# sed 's/init//g' rclocal.txt
#!/bin/sh
#
# This script will be executed *after* all the other scripts.
# You can put your own ialization stuff in here if you don't
# want to do the full Sys V style stuff.
6
touch /var/lock/subsys/local

删除所有的“script”、所有的“stuff”、所有的字母e,或者的关系用转义方式 \| 来表示:

1
2
3
4
5
6
7
8
[root@svr5 ~]# sed 's/script\|stuff\|e//g' rclocal.txt
.1 #!/bin/sh
#
# This will b xcutd *aftr* all th othr init s.
# You can put your own initialization in hr if you don't
# want to do th full Sys V styl init .
6
touch /var/lock/subsys/local

5)配置行的注释、解除注释。

解除/etc/rc.local文件第3~5行的注释(去掉开头的 # ):

1
2
3
4
5
6
7
[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

去掉所有注释(行首去掉#):

1
[root@svr5 ~]# sed 's/^//' /etc/rc.local

把开头替换为空,即去掉所有注释;其实在vi vim 编辑器里也可以这么用

将/etc/rc.local文件的第6~7行注释掉(行首添加 # ):

1
[root@svr5 ~]# sed '6,7s/^/#/' /etc/rc.local

6)小括号的应用

修改IP地址的网段部分,主机地址不变。

直接修改网卡eth0的配置文件,检查原有的配置内容:

1
2
3
4
5
6
7
8
9
[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”所在的行,执行相应的替换(仅测试,尚未修改):

1
2
3
[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 选项):

1
2
[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编辑器中的用法。




      本文转自Jx战壕  51CTO博客,原文链接:http://blog.51cto.com/xujpxm/1391845,如需转载请自行联系原作者



上一篇:《深入理解JavaScript》——1.3 变量和赋值


下一篇:Cisco设备配置文件定期备份