linux下sed的使用(下)
本篇主要讲解:
---sed的导入和导出
sed数据的导入和导出(是一种非交互式的导入和导出,可用在脚本中)
r 导入 (把其他文件的内容放到当前文件里)
w 导出 (文件另存为)
Sed导入格式
sed -i ‘定址符r 文件A’ 文件B
把文件A的数据导入到 文件B里
导入的时候是逐行导入的,B文件必须事先存在,且最少有一行,一行都没有的情况下是导入不了的
–默认会逐行导入
–使用定址符限制输入数据的位置
–定址符可以使用行号、正则表达式表示
Sed导出格式
sed -i ‘定址符w 文件A’ 文件B
把文件B的数据导出到 文件A里(另存为)
–覆盖导出
–文件A不用事先创建
–若文件A事先存在 会覆盖其内的数据
一、
1.sed导入导出的基本用法
1)r 读入其他文件内容。
以前面的rclocal.txt文件为例,确认文件内容:
1
2
3
4
5
6
7
8
|
[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
|
读入/etc/sysconfig/network文件的全部内容,插入到rclocal.txt文件的第5行之后(注意:需加-i才真的保存,否则只输出结果):
1
2
3
4
5
6
7
8
9
10
11
|
[root@svr5 ~] # sed '5r /etc/sysconfig/network' 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.
NETWORKING= yes
NETWORKING_IPV6=no HOSTNAME=svr5.tarena.com 6 7 touch /var/lock/subsys/local
|
在rclocal.txt文件的每一行下方都插入/etc/sysconfig/network文件的内容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
[root@svr5 ~] # sed 'r /etc/sysconfig/network' rclocal.txt
1 #!/bin/sh
NETWORKING= yes
NETWORKING_IPV6=no HOSTNAME=svr5.tarena.com 2 #
NETWORKING= yes
NETWORKING_IPV6=no HOSTNAME=svr5.tarena.com 3 # This script will be executed *after* all the other init scripts.
NETWORKING= yes
NETWORKING_IPV6=no HOSTNAME=svr5.tarena.com .. .. |
2)w 将过滤结果保存到指定的文件。
以前面的rclocal.txt文件为例,确认文件内容:
1
2
3
4
5
6
7
8
|
[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
|
将rclocal.txt文件的第2-5行保存为/tmp/out.txt文件:
1
2
3
4
5
6
|
[root@svr5 ~] # sed -n '2,5w /tmp/out.txt' rclocal.txt
[root@svr5 ~] # cat /tmp/out.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.
|
上述操作与改用p重定向的效果相同:
1
2
3
4
5
6
|
[root@svr5 ~] # sed -n '2,5p' rclocal.txt > /tmp/out.txt
[root@svr5 ~] # cat /tmp/out.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.
|
再比如:将rclocal.txt文件中包含“init”的行保存为/tmp/out.txt文件:
1
2
3
4
5
|
[root@svr5 ~] # sed -n '/init/w /tmp/out.txt' rclocal.txt
[root@svr5 ~] # cat /tmp/out.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.
|
效果等同于:
1
2
3
4
5
|
[root@svr5 ~] # sed -n '/init/p' rclocal.txt > /tmp/out.txt
[root@svr5 ~] # cat /tmp/out.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.
|
2.sed的复制粘贴操作
1)基本动作指令
复制到剪贴板:
H:模式空间 ---[追加]--->保持空间
h:模式空间 ---[覆盖]--->保持空间
读取剪贴板内容并粘贴:
G:保持空间 ---[追加]--->模式空间
g:模式空间 ---[覆盖]--->保持空间
若要实现“剪切”操作,实际上就是先“复制”再“删除”。
讲一下sed的2个空间:
模式空间:
--存放当前处理的行,将处理结果输出
--若当前行不符合处理条件,则原样输出
--处理完当前行再读入下一行来处理
保持空间:
--作用类似于”剪贴板“
--默认存放一个空行(换行符\n)
2)复制操作练习
还以rclocal.txt文件为例:
1
2
3
4
5
6
7
8
|
[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
|
将第rclocal.txt文件的第1-3行内容复制到文件末尾:
1
2
3
4
5
6
7
8
9
10
11
|
[root@svr5 ~] # sed '1,3H;$G' 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 #!/bin/sh
2 #
3 # This script will be executed *after* all the other init scripts.
|
从上述结果可以发现,使用G粘贴操作的效果是追加。但是,文件原内容与新追加的文本之间还有一个空行,这是怎么来的呢?这是保持空间默认的内容“\n”,追加操作时就保留了。那么,如果将G追加改为g覆盖来粘贴,结果会怎么样呢?看看:
1
2
3
4
5
6
7
8
9
10
|
[root@svr5 ~] # sed '1,3H;$g' 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 1 #!/bin/sh
2 #
3 # This script will be executed *after* all the other init scripts.
|
什么情况?把原文件的最后一行给覆盖了。如果既要保留原文件的所有内容,又想复制前3行到文件末尾,而且不希望有空行分开,怎么办呢?把复制操作H追加改成h覆盖试试看什么结果:
1
2
3
4
5
6
7
8
9
|
[root@svr5 ~] # sed '1,3h;$G' 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
8 # This script will be executed *after* all the other init scripts.
|
这下原文件内容是保留了,空行也没了,但是追加的内容却只有第3行,为什么?
因为sed是逐行处理的,所以每次h覆盖操作都会清空原来存放在保持空间的文本,也就是说用h复制第1行到保持空间后,默认的“\n”就没了;再用h复制第2行到保持空间后,前一次复制过去的第1行文本又没了;再用h复制第3行到保持空间后,前一次复制过去的第2行文本又没了,…… 于是,最终只有匹配的最后一行能够成功添加。
总和上述分析,我们可以在复制第一行的时候用h覆盖,而以后的每一行用H追加,这样就可以完美无空行的追加匹配行了:
1
2
3
4
5
6
7
8
9
10
11
|
[root@svr5 ~] # sed '1h;2,3H;$G' 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 #!/bin/sh
2 #
3 # This script will be executed *after* all the other init scripts.
|
3)剪切操作练习
将rclocal.txt文件的第1-4行转移到文件末尾:
1
2
3
4
5
6
7
8
|
[root@svr5 ~] # sed '1{h;d};2,4{H;d};$G' rclocal.txt
5 # want to do the full Sys V style init stuff.
6 7 touch /var/lock/subsys/local
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
|
将包含单词“init”的行剪切到文件末尾,保留默认的空行分隔:
1
2
3
4
5
6
7
8
|
[root@svr5 ~] # sed '/\<init\>/{H;d};$G' rclocal.txt
1 #!/bin/sh
2 #
4 # You can put your own initialization stuff in here if you don't
6 7 touch /var/lock/subsys/local
3 # This script will be executed *after* all the other init scripts.
5 # want to do the full Sys V style init stuff.
|
二、扩展
1.sed逐字符替换
sed的s操作可实现字符串替换,而另一个操作y操作可实现逐个字符替换。
什么意思呢?对比一下:
's/OLD/NEW/g' ,处理方式为整串匹配,只匹配完整的字符串“OLD”,对单个字符“O”、“L”或者“D”无效,而且替换前后的字符串长度可以不相同(比如,“OLD”可替换为“NEWNEW”)。实现的效果是——将文本中所有的字符串“OLD”替换为“NEW”。
'y/abcd/ABCD/',处理的方式为逐个字符依次替换,替换前后的内容必须一一对应、数量一致。实现的效果是——将文件内所有的字符“a”替换为“A”、字符“b”替换为“B”、字符“c”替换为“C”、字符“d”替换为“D”。
下面仍以rclocal.txt文件为例,测试一下y操作的相关效果。
确认rclocal.txt文件内容:
1
2
3
4
5
6
7
8
|
[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)将所有的小写字母i替换为大写的I:
1
2
3
4
5
6
7
8
|
[root@svr5 ~] # sed 'y/i/I/' 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
2
3
4
5
6
7
8
|
[root@svr5 ~] # sed 's/i/I/g' 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)将所有的小写字母a、e、l替换为大写:
1
2
3
4
5
6
7
8
|
[root@svr5 ~] # sed 'y/ael/AEL/' 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
2
3
4
5
6
7
8
|
[root@svr5 ~] # sed 's/a/A/g;s/e/E/g;s/l/L/g' 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
|
3)将所有的字符a变为数字1、字符e变为数字5、字符l变为变为字符X:
1
2
3
4
5
6
7
8
|
[root@svr5 ~] # sed 'y/ael/159/' rclocal.txt
1 #!/bin/sh
2 #
3 # This script wi99 b5 5x5cut5d *1ft5r* 199 th5 oth5r init scripts.
4 # You c1n put your own initi19iz1tion stuff in h5r5 if you don't
5 # w1nt to do th5 fu99 Sys V sty95 init stuff.
6 7 touch /v1r/9ock/subsys/9oc19
|
2.单词的大小写转换
将匹配结果转大写可用\U&、转小写可用\L&,这里的&为调用的匹配串。
还以前面的rclocal.txt文件为例,确认内容如下:
1
2
3
4
5
6
7
8
|
[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)将所有的小写字母转为大写:
1
2
3
4
5
6
7
8
|
[root@svr5 ~] # sed 's/[a-z]/\U&/g' 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
2
3
4
5
6
7
8
|
[root@svr5 ~] # cat rclocal.txt | tr [:lower:] [:upper:]
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)将所有的大写字母转为小写:
1
2
3
4
5
6
7
8
|
[root@svr5 ~] # sed 's/[A-Z]/\L&/g' 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
2
3
4
5
6
7
8
|
[root@svr5 ~] # cat rclocal.txt | tr [:upper:] [:lower:]
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
|
3)将每个单词的首字母大写:
1
2
3
4
5
6
7
8
|
[root@svr5 ~] # sed -r 's/\b[a-Z]/\U&/g' 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
|
4)将每个单词的首字母大写,其余字母小写:
1
2
3
4
5
6
7
8
|
[root@svr5 ~] # sed -r 's/([a-Z])([a-Z]+)/\U\1\L\2/g' 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、若要实现“剪切”操作,实际上就是先“复制”再“删除”。
2、因为保持空间默认会有一个换行符号,所以把模式空间的内容放到保持空间的时候,第一行用h覆盖来把换行符给覆盖掉,这样就不会出现一行空格
本文转自Jx战壕 51CTO博客,原文链接:http://blog.51cto.com/xujpxm/1391849,如需转载请自行联系原作者