三剑客之老二sedlinux |
咱们都知道,在Linux中一切皆文件,好比配置文件,日志文件,启动文件等等。若是咱们相对这些文件进行一些编辑查询等操做时,咱们可能会想到一些vi,vim,cat,more等命令。可是这些命令效率不高,这就比如一块空地准备搭建房子,请了10个师傅拿着铁锹挖地基,花了一个月的时间才挖完,而另一块空地则请了个挖土机,三下五除二就搞定了,这就是效率。而在linux中的“挖土机”有三种型号:顶配awk,中配sed,标配grep。使用这些工具,咱们可以在达到一样效果的前提下节省大量的重复性工做,提升效率。面试
接下来咱们就看一下sed的详细说明正则表达式
sed 是Stream Editor(字符流编辑器)的缩写,简称流编辑器。什么是流?你们能够想象如下流水线,sed就像一个车间同样,文件中的每行字符都是原料,运到sed车间,而后通过一系列的加工处理,最后从流水线下来就变成货物了。shell
sed是非交互式的编辑器。它不会修改文件,除非使用shell重定向来保存结果。默认状况下,全部的输出行都被打印到屏幕上。express
sed编辑器逐行处理文件(或输入),并将结果发送到屏幕。具体过程以下:首先sed把当前正在处理的行保存在一个临时缓存区中(也称为模式空间),而后处理临时缓冲区中的行,完成后把该行发送到屏幕上。sed每处理完一行就将其从临时缓冲区删除,而后将下一行读入,进行处理和显示。处理完输入文件的最后一行后,sed便结束运行。sed把每一行都存在临时缓冲区中,对这个副本进行编辑,因此不会修改原文件。vim
固然上图中的文件内容能够是来自文件,也能够直接来自键盘或者管道等标准输入,最后的结果默认状况下是显示到终端的屏幕上,可是也能够输出到文件中。缓存
之前工厂中没有流水线时,生产一件商品须要十几个工种互相配合,这样下来利润过低,后来就有了流水线,生产一件商品虽然仍是有十几道工序,但都是机器化生产,工人只是辅助做用,这样利润就大大提升了,产量也大大提升了。bash
编辑文件也是这样,之前咱们修改一个配置文件,须要移动光标到某一行,而后添加点文字,而后又移动光标到另外一行,注释点东西.......可能修改一个配置文件下来须要花费数十分钟,还有可能改错了配置文件,又得返工。这仍是一个配置文件,若是数十个数百个呢?所以当你学会了sed命令,你会发现利用它处理文件中的一系列修改是颇有用的。只要想到在大约100多个文件中,处理20个不一样的编辑操做能够在几分钟以内完成,你就会知道sed的强大了。less
Sed命令是操做,过滤和转换文本内容的强大工具。经常使用功能有增删改查(增长,删除,修改,查询),其中查询的功能中最经常使用的2大功能是过滤(过滤指定字符串),取行(取出指定行)。ssh
sed版本是GNU开源版本的,个人实验环境是CentOS6.8系统,内核版本是2.6.32-642.el6.x86_64
[root@kaile /]# cat /etc/redhat-release #查看Linux版本
CentOS release 6.8 (Final)
[root@kaile /]# uname -r #查看内核版本
2.6.32-642.el6.x86_64
[root@kaile /]# sed --version #使用的sed版本
GNU sed 版本 4.2.1
sed [options] [sed -commands][input -file]
sed [选项] 【sed命令】【输入文件】
说明:
1 注意sed软件以及后面选项,sed命令和输入文件,每一个元素之间都至少有一个空格。
2 为了不混淆,本文称呼sed为sed软件。sed -commands(sed命令)是sed软件内置的一些命令选项,为了和前面的options(选项)区分,故称为sed命令
3 sed -commands 既能够是单个sed命令,也能够是多个sed命令组合。
4 input -file (输入文件)是可选项,sed还可以从标准输入如管道获取输入。
Sed软件从文件或管道中读取一行,处理一行,输出一行;再读取一行,再处理一行,再输出一行....
一次一行的设计使得sed软件性能很高,sed在读取很是庞大的文件时不会出现卡顿的想象。你们都用过vi命令,用vi命令打开几十M或更大的文件,会发现有卡顿现象,这是由于vi命令打开文件是一次性将文件加载到内存,而后再打开,所以卡顿的时间长短就取决于从磁盘到内存的读取速度了。并且若是文件过大的话还会形成内存溢出现象。Sed软件就很好的避免了这种状况,打开速度很是快,执行速度也很快。
现有一个文件person.txt,共有五行文本,sed命令读入文件person.txt的第一行“101,zhaokai,CEO”,并将这行文本存入模式空间(sed软件在内存中的一个临时缓存,用于存放读取到的内容,比喻为工厂流水线的传送带。)
1,判断第1行是不是须要处理的行,若是不是要处理的行就从新从文件读取下一行,若是是要处理的行,则接着往下走。
2,对模式空间的内容执行sed命令,好比a(追加),i(插入),s(替换)...
3,将模式空间中通过sed命令处理后的内容输出到屏幕上,而后清空模式空间
4,读取下一行文本,而后从新执行上面的流程,直到文件结束
模式空间(pattern space):是sed软件从文本读取一行文本而后存入的缓冲区(这个缓冲区是在内存中的),而后使用sed命令操做模式空间的内容。
保持空间(hold space):是sed软件另一个缓冲区,用来存放临时数据,也是在内存中,可是模式空间和保持空间的用途是不同的。Sed能够交换保持空间和模式空间的数据,可是不能在保持空间上执行普通的sed命令,也就是说咱们能够在保持空间存储数据。
option[选项] |
解释说明(带*的为重点) |
-n |
取消默认的sed软件的输出,常与sed命令的p连用。* 取消模式空间的默认输出 |
-e |
一行命令语句能够执行多条sed命令 sed '2d';'1i ceshi' test.txt |
-f |
选项后面能够接sed脚本的文件名 |
-r |
使用扩展正则表达式,默认状况sed只识别基本正则表达式* 扩展正则 +连续重复前面一个字符或多个字符 ()分组替换 括号里面的字符保护起来后向引用 |
-i |
直接修改文件内容,而不是输出到终端,若是不使用-i选项sed软件只是修改在内存中的数据,并不会影响磁盘上的文件* |
a |
追加,在指定行后添加一行或多行文本* |
c |
取代指定的行 替换指定行 sed '1c ceshi' test.txt |
d |
删除指定的行* $最后一行 sed '1,5d' 删除一到5行内容 sed '5,$' 删除5到最后一行 |
D |
删除模式空间的部份内容,直到遇到换行符\n结束操做,与多行模式相关 |
i |
插入,在指定行前添加一行或多行文本* |
h |
把模式空间的内容复制到保持空间 |
H |
把模式空间的内容追加到保持空间 |
g |
把保持空间的内容复制到模式空间 |
G |
把保持空间的内容追加到模式空间 |
x |
交换模式空间和保持空间的内容 |
l |
打印不可见的字符 |
n |
清空模式空间的内容并读入下一行 |
N |
不清空模式空间,并读取下一行数据并追加到模式空间* |
p |
打印模式空间内容,一般p会与选项-n一块儿使用* |
P(大写) |
打印模式空间的内容,直到遇到换行符\n结束操做 |
q |
退出Sed |
r |
从指定文件读取数据 |
s |
取代,s#old#new#g==>这里g是s命令的替代标志,注意和g命令区分。s命令替换* |
w |
另存,把模式空间的内容保存到文件中 |
y |
根据对应位置转换字符 |
:label |
定义一个标签 |
b label |
执行该标签后面的命令 |
t |
若是前面的命令执行成功,那么就跳转到t指定的标签处,继续往下执行后续命令。不然,仍然继续正常的执行流程 |
特殊符号 |
解释说明(带*的为重点) |
! |
对指定行之外的全部行应用命令* |
= |
打印当前行行号 |
~ |
“First~step”表示从First行开始,以步长Step递增 sed '1~3' |
& |
表明被替换的内容 |
; |
实现一行命令语句能够执行多条sed命令* |
{} |
对单个地址或地址范围执行批量操做 |
+ |
地址范围中用到的符号,作加法运算 |
为了更好的测试sed命令的用法,咱们须要准备好下面的测试文件。
[root@kaile ~]# cat>person.txt<<EFO
> 101,zhaokai,CEO
>102,zhangyang,CTO
> 103,Alex,COO
> 104,yy,CFO
> 105,feixue,CIO
> EFO #EFO必须成对出现,表示终止输入
命令说明:使用一条cat命令建立多行文本,文件包含上面的内容,后面的操做都会使用这个文件。
接下来我来教你们第一式招法-->往文件指定位置追加或插入指定文本。
这个功能很是有用,好比咱们平时往配置文件写入几行文本,最经常使用的是vi或vim命令,可是这2个命令是一种交互式的命令,还须要咱们在vi/vim编辑器界面输入字符串而后保存退出,操做有些繁琐可是还能用。可是当咱们学会了Shell脚本后,咱们就会发如今脚本中不能正常使用vi或vim命令,为何呢?同窗们请自行体验。
咱们学习Shell脚本主要是为了解放咱们的双手,执行一个脚本,而后自动往文件中写入数据,不须要咱们再动手。所以咱们想到了sed软件,它可以帮助咱们实现目的。
这里咱们须要用到2个sed命令,分别是:
“a”:追加文本到指定行后,记忆方法:a的全拼是apend,意思是追加。
“i“:插入文本到指定行前,记忆方法:i的全拼是insert,意思是插入。
首先咱们看一下单行增长的用法,说白了就是在文件中增长一行文本,咱们之前学过echo命令能够在文件的末尾追加文本,比较简单,可是咱们还有其余的复杂需求,好比在第10行插入一行数字等等,这里就须要sed出马了。咱们来看一下下面的例子,同窗也跟着例子一块儿练习,命令只有多练才会熟悉,光看永远是学不会的。
#在文件person.txt 文件第一行追加 dan,CEO
[root@kaile ~]# sed '1a dan,CEO' person.txt # 1表明一行 a 表明追到到指定行号
101,zhaokai,CEO
dan,CEO #追加的内容
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
##在文件person.txt 文件第五行插入 oldboy
[root@kaile ~]# sed '5i oldboy' person.txt
101,zhaokai,CEO
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
oldboy
105,feixue,CIO
命令行详解:
首先咱们看一下命令的结果,咱们能够看到原来的第二行“102,zhangyang,CTO” 前面插入了新的一行为“dan,CEO”,原来的第2行变成第3行了。
接下来咱们解读一下sed语句的结构,sed打头,而后接上空格(空格个数不限,但至少要有一个!)在空格后面,咱们先敲上一对单引号(“)而后退格在单引号中协商‘dan,CEO’。
5表明指定对第5行操做,其余的行忽略
i表明插入的意思,5i即在第5行前插入文本
5i后面加上空格,而后跟上你想要插入的文本便可
[root@kaile~]# cat person.txt
101,zhaokai,CEO
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
#单引号--文本内容原封不动插入
[root@kaile ~]# sed '2i $LANG' person.txt
101,zhaokai,CEO
$LANG
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
#不加引号,linux没法辨认空格,不会把有空格的命令当成一条命令来执行
[root@kaile ~]# sed 2i $LANG person.txt
sed:-e 表达式 #1,字符 2:指望在“a”, “c”, “i”以后有“\”
#双引号--变量$LANG被解析之后在看成文本进行插入
[root@kaile ~]# sed "2i $LANG"person.txt
101,zhaokai,CEO
zh_CN.GB2312
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
sed中到底使用单引号仍是双引号?
双引号:把双引号的内容输出出来;若是内容中有命令,变量等,会先把命令,变量解析出结果,而后再输出最终内容来。双引号内命令或变量的写法为`命令或变量`或$(命令或变量)
[root@kaile ~]# echo "$LANG"
zh_CN.GB2312
单引号:所见即所得,将单引号内的内容原样输出,阻止全部字符的转义
[root@kaile ~]# echo '$LANG'
$LANG
不加引号:不会将含有空格的字符串视为一个总体输出,若是内容中有命令,变量等,会先把命令,变量解析出结果,而后再输出最终内容来,若是字符串含有空格等特殊字符,则不能完整输出,则需改加双引号。
[root@kaile ~]# echo ceshi
ceshi
[root@kaile~]# echo $LANG
zh_CN.GB2312
倒引号(反引号Esc键下方):进行命令的替换,在倒引号内部的shell命令将会被执行,其结果输出代替用倒引号括起来的文本。
若是引号里面是普通字符串的话,你能够任意使用单引号或者双引号:
若是引号里面是变量或者带反引号的命令的话,你想要变量解析的结果或者命令执行的结果,那就使用双引号;你想要引号内的原样字符串,那就使用单引号。
只要你们理解上面的用法,明白本身想要什么,那么你想用什么引号就用什么引号。
其实就二选一,非此即彼,这个不行就试试那个。
前面学习的内容已经实现了往文件追加或插入单行文本,可是还有插入多行文本的需求,咱们也学习过cat命令可以往文件中追加多行文本。
[root@kaile ~]# cat test.txt
welcome to my blog.http://kaile.blog.51cto.com
空行
if you like my blog\'s contents,pls support me.
空行
空行
bye!boys and girls.
命令说明:以上就是cat的生产环境经常使用的生成或为文件追加内容的方法,请不要忽略上文中的空行。另外,若是内容中有单引号,$符号等特殊符号做为内容时要用“\”转义。
[root@kaile ~]# echo 'zhao';echo 'kai' ; 分割符 链接两条命令,而后输出结果为2行
zhao
kai
[root@kaile ~]# echo -e 'zhao\nkai' #换行符\n
zhao
kai
学习完换行符,咱们看一下sed命令如何使用
[root@kaile ~]# sed '2axiaokai\nxiaodong\nxiaoyue' person.txt
101,zhaokai,CEO
102,zhangyang,CTO
xiaokai
xiaodong
103,Alex,COO
104,yy,CFO
105,feixue,CIO
命令行分析:
咱们首先粗略扫一眼这个命令语句,能够发现命令结构是和单行增长文本是几乎没有区别的。
而后咱们看一下命令的结果,咱们能够看到原来的第二行“102,zhangyang,CTO”后面追加了2行文本“xiaokai,”和“xiaodong”。
接下来咱们解读一下sed语句的结构,sed软件打头,而后接上空格,在空格后面,咱们先敲上一对单引号(' '),而后退一格在单引号中写上‘2a xiaokai\nxiaodong’。
2表明指定对第2行操做,其余的行忽略;
a表明追加的意思,2a即在第2行后追加文本;
2a后面加上空格,而后跟上你想要插入的多行文本便可。这里的每行文本使用“\n”链接就能够写成一行了。
删除指定行文本。
这个功能也是很是得有用,好比咱们想删除文件中的某些行,之前最经常使用的是vi或vim命令,但如今咱们知道了sed命令,就应该使用这个高逼格的命令完成任务了。
这里咱们须要用到1个sed命令;
“d”:删除文本,记忆方法:d的全拼是delete,意思是删除。
由于删除功能比较简单,所以咱们结合地址范围一块儿说明。咱们前面学过sed命令能够对一行文本为目标进行处理(在单行先后增长一行或多行文本),接下来咱们看一下如何对多行文本为目标操做。
sed软件能够对单行或多行文本进行处理。若是在sed命令前面不指定地址范围,那么默认会匹配全部行。
用法:n1[,n2]{sed-commands}
地址用逗号分隔开,n1,n2能够用数字,正则表达式,或者两者的组合表示。
地址范围 |
含义 |
10{sed-commands} |
对第10行操做
sed -n '10p' person.txt sed '10d' person.txt |
10,20{sed-commands} |
对10到20行操做,包括第10,20行
sed '10,20d' person.txt #10行20行删除 sed -n '10,20p' person.txt #10到20行打印输出 |
10,+20{sed-commands} |
对10到30(10+20)行操做,包括第10,30行
如:sed -n '10,+20p' person.txt |
1~2{sed-commands} |
对1,3,5,7.....行操做 奇数偶数
sed '1~3d' person.txt 删除奇数 |
10,\${sed-commands} |
对10到最后一行($表明最后一行)操做,包括第10行 sed -n '10,$p' person.txt |
/kaile/{sed-commands} |
对匹配kaile的行操做 |
/kaile/,/Alex/{sed-commands} |
对匹配kaile的行到匹配Alex的行操做 |
/kaile/,\${sed-commands} |
对匹配kaile的行到最后一行操做 |
/kaile/,10{sed-commands} |
对匹配kaile的行到第10行操做, |
1,/Alex/{sed-commands} |
对第1行到匹配Alex的行操做 |
/kaile/,+2{sed-commands} sed '/2/,+2d' person.txt |
对匹配kaile的行到其后的2行操做 |
下面用具体的例子演示一下,测试文件仍是person.txt
[root@kaile~]
# sed 'd' person.txt
[root@kaile~]
#
命令说明:若是在sed命令前面不指定地址范围,那么默认会匹配全部行,而后使用d命令删除功能就会删除这个文件的全部内容
[root@kaile~]
# sed '2d' person.txt
101,kaile,CEO
103,Alex,COO
104,yy,
CFO
105,feixue,
CIO
命令说明:这个单行删除想必你们能理解,指定删除第2行的文本102,zhangyang,CTO
[root@kaile~]
# sed '2,5d' person.txt
101,kaile,CEO
命令说明:‘2,5d’指定删除第2行到第5行的内容,d表明删除操做。
ok,上面咱们实验完了数字地址范围,接下来咱们实验一下正则表达式的地址范围,虽说可使用正则表达式,可是咱们仍是习惯写出完整的匹配字符串,达到精确匹配的目的。
[root@kaile~]
# sed '/zhangyang/d' person.txt
101,kaile,CEO
103,Alex,COO
104,yy,
CFO
105,feixue,
CIO
命令说明:
在sed软件中,使用正则的格式和awk同样,使用2个”/“包含指定的正则表达式,即“/正则表达式/”。
固然也可使用两个正则表达式,以下例所示。
[root@kaile~]
# sed '/kaile/,/Alex/d' person.txt
104,yy,
CFO
105,feixue,
CIO
命令说明:这是正则表达式形式的多行删除,也是以逗号分隔2个地址,最后结果是删除包含“kaile”的行到包含“Alex”的行
[root@kaile~]
# sed '3,$d' person.txt
101,kaile,CEO
102,zhangyang,CTO
命令说明:学过正则表达式后咱们知道“$”表明行尾,可是在sed中就有一些变化了,“$”在sed中表明文件的最后一行。所以本例子的含义是删除第3行到最后一行的文本,包含第3行和最后一行,所以剩下第1,2行的内容。
接下来咱们看一些特殊状况。
[root@kaile~]
# sed '/kaile/,3d' person.txt
104,yy,
CFO
105,feixue,
CIO
命令说明:这个例子是删除包含“kaile”的行到第3行的内容。但这种组合有一个比较特殊的状况,若是前3行以外还有这个“kaile”字眼,sed软件仍是会找他“麻烦”,请看下面例子。
[root@kaile~]
# sed '$a 106,kaile,CMO' person.txt
101,kaile,CEO
102,zhangyang,CTO
103,Alex,COO
104,yy,
CFO
105,feixue,
CIO
106,kaile,CMO
命令说明:为了避免形成同窗们实验文本改来改去致使不一样意,所以我用上面的命令语句只是临时修改内存数据,而后经过管道符号传给sed软件。
[root@kaile~]
# sed '$a 106,kaile,CMO' person.txt | sed '/kaile/,3d'
104,yy,
CFO
105,feixue,
CIO
命令说明:从命令结果咱们能够看到,不只是第1行(101,kaile,CEO)到第3行(103,ALex,COO)被删除了,并且最后一行(106,kaile,CMO)也被删除了。所以咱们能够得出一个小结论,sed软件使用正则表达式会找出全部匹配的行,即便是有数字地址限制。
再来看一个特殊状况。
[root@kaile~]
# sed '2,/O/d' person.txt
101,kaile,CEO
104,yy,CFO
105,feixue,CIO
命令说明:
从第2行开始删除到含字母O的行结束,可是咱们发现第3,4,5行都含有字母O,命令结果显示只删除了第2,3行,属于最短删除。这个怎么理解?
仍是能够从上面命令执行流程图理解,从第2行开始循环,sed软件第一次遇到字母O(第三行)就认为循环结束了。
[root@kaile~]
# sed '2,/o/d' person.txt
101,kaile,CEO
命令说明:
从第2行开始删除,可是后面文本没有字母O,所以一直循环下去,直到文本结束,sed软件自动终止。
你们看完上面的例子是否是一脸懵逼,其实很简单。在工做中咱们最经常使用的仍是数字地址这种精确匹配方式,像上面的正则地址或混合地址这种模糊匹配用的比较少,了解便可。
格式:“First~step”表示从开始,以步长step递增,这个在数学中叫作等差数列
例子:
1~2 匹配1,3,5,7.....#-->用于只输出奇书行,大伙仔细观察一下每一个数字的差值。
2~2 匹配2,4,6,8....#-->用于只输出偶数行
1~3 匹配1,4,7,10.....
2~3 匹配2,5,8,11.....
[root@kaile~]
# seq 10
1
2
3
4
5
6
7
8
9
10
命令说明:seq命令可以生成从1到10的数字序列。
[root@kaile~]
# seq 10 | sed -n '1~2p'
1
3
5
7
9
命令说明:
上面的命令主要验证特殊符号“~”的效果,其余sed命令用法n和p请见后文详解,你们只须要知道这个命令能够将“1~2”指定的行显示出来便可。
上面例子测试了“1~2”的效果,你们也能够手动测试一下“2~2”,“1~3”,“2~3”,看一下他们的结果是否是符合等差数列。
补充小知识:
若是你们想生成奇数数列,其实上面的方法是为了举例,并非一个很好的方法,由于seq命令自带这种功能。
[root@kaile~]
# seq 1 2 10
1
3
5
7
9
命令说明:seq命令格式seq起始值 公差 结束值
再来一例:
[root@kaile~]
# sed '1~2d' person.txt
102,zhangyang,CTO
104,yy,CFO
命令说明:“1~2”这是指定行数的另外一种格式,从第1行开始以步长2递增的行(1,3,5),所以删掉第1,3,5行,即全部的奇数行。
命令说明:seq命令格式seq起始值 公差 结束值
再来一例:
[root@kaile1~]
# sed '1~2d' person.txt
102,zhangyang,CTO
104,yy,CFO
命令说明:“1~2”这是指定行数的另外一种格式,从第1行开始以步长2递增的行(1,3,5),所以删掉第1,3,5行,即全部的奇数行。
[root@kaile1~]
# sed '1,+2d' person.txt
104,yy,
CFO
105,feixue,
CIO
命令说明:这实际上是作个加法运算,‘1,+2d’==>删除第1行到第3(1+2)行的文本。
上面是特殊符号“+”的用法,你们知道便可。
感叹号“!”咱们在不少命令里都接触过,大部分都是取反的意思,在sed中也不例外。
[root@kaile1 ~]# sed '2,3!d' person.txt
102,zhangyang,CTO
103,Alex,COO
命令说明:在地址范围“2,3”后面加上“
!”,若是不加“!”表示删除第2行和第3行,结果以下面的例子所示,而后加上“!”的结果就是除了第2行和第3行之外的内容都删除,这个方法能够做为显示文件的第2,3行题目的补充方法。
[root@kaile1 ~]# sed '2,3d' person.txt
101,kaile,CEO
104,yy,CFO
5105,feixue,CIO
这是一道企业面试题,很简单,就是把包含kaile字符串的行删除掉便可。咱们能够用“grep -v”取反获得咱们想要的结果,可是这里咱们使用sed软件实现。
[root@kaile1 ~]# sed '/kaile/d' person.txt
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
你们如今已经学完了sed软件2大招式,是否是很厉害!固然后面还有更厉害的--->改.在学习linux时,咱们最多见的操做就是改配置文件,改参数等等,并且更妙的是前面咱们学习过的增长和删除其实均可以用咱们准备要学的修改变相实现。
首先说一下按行替换,这个功能用的不多,因此你们了解便可。这里用到的sed命令是:
“c”:用新行取代旧行,记忆方法:c的全拼是change,意思是替换。
例子:
[root@kaile ~]# sed '2c 106,dandan,CSO' person.txt
101,kaile,CEO
106,dandan,CSO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
命令说明:使用sed命令c将原来第2行“102,zhangyang,CTO”替换成“106,dandan,CSO”,整行替换
接下来讲的这个功能,有工做经验的同窗应该很是的熟悉,由于使用sed软件80%的场景就是使用替换功能。
这里用到的sed命令,选项:
“s”:单独使用-->将每一行中第一处匹配的字符串进行替换==>sed命令
“g”:每一行进行所有替换-->sed命令s的替换标志之一(全局替换),非sed命令。
“-i”:修改文件内容-->sed软件的选项,注意和sed命令i区别。
sed -i 's/目标内容/替换内容/g'kaile.log
sed -i 's#目标内容#替换内容#g'
1,两边是引号,引号里面的两边分别为s和g,中间是三个同样的字符/或#做为定界符。字符#能在替换内容包含字符/有助于区别。定界符能够是任意字符如:或|等,但当替换内容包含定界符时,须要转义\:或\|.通过长期实践,建议你们使用#做为定界符。
2,定界符/或#,第一个和第二个之间的就是被替换的内容,第二个和第三个之间的就是替换后的内容。
3,s#目标内容#替换内容#g ,“目标内容”能用正则表达式,但替换内容不能用,必须是具体的。由于替换内容使用正则的话会让sed软件无所适从,它不知道你要替换什么内容。
4,默认sed软件是对模式空间(内存中的数据)操做,而-i选项会更改磁盘上的文件内容。
例子:
[root@kaile~]
# sed 's#zhangyang#dandan#g' person.txt
101,kaile,CEO
102,dandan,CTO
103,Alex,COO
104,yy,
CFO
105,feixue,
CIO
命令说明:将须要替换的文本“zhangyang”放在第一个和第二个“#”之间,将替换后的文本“dandan”放在第二个核第三个“#”之间。结果为第二行的“zhangyang”替换为“dandan”。
修改文件:
[root@kaile~]
# cat person.txt
101,kaile,CEO
102,zhangyang,CTO
103,Alex,COO
104,yy,
CFO
105,feixue,
CIO
命令说明:从上面命令的结果咱们就知道sed命令默认不会修改文件的内容
[root@kaile~]
# sed -i 's#zhangyang#dandan#g' person.txt
命令说明:若是想真正的修改文件内容,咱们就须要使用选项“-i”,这个要和sed命令“i”区分开来。同时咱们能够发现命令执行后的结果是没有任何输出的。
[root@kaile~]
# cat person.txt
101,kaile,CEO
102,dandan,CTO
103,Alex,COO
104,yy,
CFO
105,feixue,
CIO
命令说明:当咱们再次查看这个文件时,咱们就发现这个文件已经被修改为功了。所以你们之后若是使用替换功能时,应该首先不用选项“-i”测试一下,确保操做无误,最后使用“-i”修改文件
还原测试文件:
[root@kaile~]
# sed -i 's#dandan#zhangyang#g' person.txt
命令说明:还原测试文件,这一步你们不要忘了执行,否则后面就跟不上步骤了
前面咱们学过的模型可以将文件中全部知足条件的文本进行操做,可是咱们也会碰到指定行精确修改配置文件的需求,由于这样能够避免修改多了地方。
[root@kaile~]
# sed '3s#0#9#' person.txt
101,kaile,CEO
102,zhangyang,CTO
193,Alex,COO
104,yy,
CFO
105,feixue,
CIO
命令说明:
前面学习的例子在sed命令“s”前没有指定地址范围,所以默认是对全部行进行操做。
而这个案例要求只将第3行的0换成9,这里就用到了咱们前面学过的地址范围知识,在sed命令“s”前加上“3”就表明对第3行进行替换
变量替换其实和前面的文本替换是同样的,就是具体的文本变成了变量,同时要求你们对引号的用法要有清晰的理解,所以对双引号和单引号的区别不太理解的同窗,请往前面翻页到【引号的区别总结】再次复习一下。
[root@kaile~]
# cat >test.txt<<KOF #再新建一个简单的测试文本
> a
> b
> a
>KOF
[root@kaile~]
# cat test.txt
a
b
a
[root@kaile~]
# x=a #->设置变量x并赋值a
[root@kaile~]
# y=b #-> 设置变量y并赋值b
[root@kaile~]
# echo $x
a
[root@kaile~]
# echo $x $y
a b
命令说明:打印变量x,y验证一下,须要使用$符号引用变量
不使用引号:
[root@kaile ~]# sed s#$x#$y#g test.txt
b
b
b
命令说明:使用变量进行替换,从执行结果中咱们能够发现替换成功了,test.txt文件中全部的a都替换成了b。同时咱们能够发现s#$x#$y#g没有使用引号,固然这种写法并非特别标准。
[root@kaile ~]# sed 's#'$x'#'$y'#g' test.txt
b
b
b
命令说明:表面看起来单引号是能够用的,但其实这里用了障眼法,在大家眼中分段‘$x’和'$y',但其实分段是‘s#’和‘#’和‘#g’,因此$x和$y并无被引号扩起来,和上面的例子就同样了。
使用eval命令:
[root@kaile ~]# eval sed 's#$x#$y#g' test.txt
b
b
b
命令说明:这里给你们扩展一个Linux内置命令eval,这个命令能读入变量,并将他们组合成一个新的命令,而后执行。首先eval会解析变量$x和变量$y,最后达到的效果和双引号是同样的。
扩展:最快速的获取IP地址的方法
[root@kaile ~]# hostname-I
192.168.197.133
sed软件的()的功能能够记住正则表达式的一部分,其中,\1为第一个记住的模式即第一个小括号中的匹配内容,\2第二个记住的模式,即第二个小括号中的匹配内容,sed最多能够记住9个。
例:echo "I am kaileteacher."若是想保留这一行的单词kaile,删除剩下部分,使用圆括号标记想保留的部分。
[root@kaile~]
# echo "I am kaile teacher." | sed 's#^.*am\([a-z]\+\) tea.*$#\1#g'
kaile
[root@kaile~]
# echo "I am kaile teacher." | sed -r 's#^.*am([a-z]+) tea.*$#\1#g'
kaile
[root@kaile~]
# echo "I am kaile teacher." | sed -r 's#I (.*)(.*) teacher.#\1\2#g'
amkaile
命令说明:
sed若是不加-r后缀,那么默认不支持扩展正则表达式,须要\符号进行转义。小括号的做用是将括号里的匹配内容进行分组以便在第2和第3个#号之间进行sed的反向引用,\1表明引用第一组,\2表明引用第二组
再来看个题目:请执行命令取出linux中的eth0的IP地址?
[root
@kaile ~]# ifconfig eth0 | sed -n
'2p'
inet addr:
192.168.197.133
Bcast:
192.168.197.255
Mask:
255.255.255.0
[root
@kaile ~]# ifconfig eth0 | sed -n
'2p' | sed -r
's#^.*addr:(.*)
Bcast:.*$#\
1#g'
192.168.197.133
进行组合
[root
@kaile ~]# ifconfig eth0 | sed -rn
'2s#^.*addr:(.*)
Bcast:.*$#\
1#gp'
192.168.197.133
命令说明:
这道题是须要把ifconfig eth0执行结果的第2行的IP地址取出来,上面答案的思路是用IP地址来替换第2行的内容。
[root
@kaile ~]# chkconfig --list | egrep-v
"sshd|crond|rsyslog|sysstat|network" | awk '{print $
1}' |sed -r
's#^(.*)#chkconfig \
1 off#g' |bash
这题也能够应用awk直接一步到位
[root
@kaile ~]# chkconfig --list | egrep-v
"sshd|crond|network|rsyslog|sysstat" | awk '{print
"chkconfig",$
1,
"off"}' | bash
这是一个特殊技巧,在适合的场景使用特别方便。下面用特殊符号“&”与分组替换一块儿使用,进行对比。
[root@kaile~]# sed -r
's#(.*),(.*),(.*)#& ----- \1 \2 \3#' person.txt
101,kaile,CEO
----- 101 kaile CEO
102,zhangyang,CTO
----- 102 zhangyang CTO
103,Alex,COO
----- 103 Alex COO
104,yy,CFO
----- 104 yy CFO
105,feixue,CIO
----- 105 feixue CIO
命令说明:
1,这里将分组替换和&符号放在一块儿对比
2,命令中的分组替换使用了3个小括号,每一个小括号分别表明每一行以逗号做为分隔符的每一列。
3,上面命令的&符号表明每一行,即模型中‘s#目标内容#替换内容#g’的目标内容。
[root@kailechen]
# find ./ -name "*_finished.jpg"
./stu_102999_1_finished.jpg
./stu_102999_5_finished.jpg
./stu_102999_3_finished.jpg
./stu_102999_2_finished.jpg
./stu_102999_4_finished.jpg
要求用sed命令重命名,效果为
stu_102999_1_finished.jpg==>stu_102999_1.jpg,即删除文件名的_finished
解题思路:由于这是文件名,不能直接yongsed命令替换,所以还须要借助mv命令重命名,格式为:mvstu_102999_1_finished.jpg stu_102999_1.jpg.咱们须要拼凑这样的格式,而后使用bash命令执行便可。
[root
@kaile chen]# find ./ -name
"*_finished.jpg" | sed -r
's#^(.*)_finished(.*)#\
1\
2#g'
./stu_102999_1.jpg
./stu_102999_5.jpg
./stu_102999_3.jpg
./stu_102999_2.jpg
[root
@kaile chen]# find ./ -name
"*_finished.jpg" | sed -r
's#^(.*)_finished(.*)#& \
1\
2#g'
./stu_102999_1_finished.jpg./stu_102999_1.jpg
./stu_102999_5_finished.jpg./stu_102999_5.jpg
./stu_102999_3_finished.jpg./stu_102999_3.jpg
./stu_102999_2_finished.jpg./stu_102999_2.jpg
./stu_102999_4_finished.jpg./stu_102999_4.jpg
[root
@kaile chen]# find ./ -name
"*_finished.jpg" | sed -r
's#^(.*)_finished(.*)#mv & \
1\
2#g'
mv./stu_102999_1_finished.jpg ./stu_102999_1.jpg
mv./stu_102999_5_finished.jpg ./stu_102999_5.jpg
mv./stu_102999_3_finished.jpg ./stu_102999_3.jpg
mv./stu_102999_2_finished.jpg ./stu_102999_2.jpg
mv./stu_102999_4_finished.jpg ./stu_102999_4.jpg
[root
@kaile chen]# find ./ -name
"*_finished.jpg" | sed -r
's#^(.*)_finished(.*)#mv & \
1\
2#g' |bash
[root
@kaile chen]# ls
stu_102999_1.jpg stu_102999_2.jpg stu_102999_3.jpg stu_102999_4.jpg stu_102999_5.jpg
命令说明:
1.“\1”表明前面“(^.*)”匹配内容,“&”表明“s# #”里被替换的内容,这里匹配到的是完整的文件名。
2.使用bash命令执行,bash命令执行标准输入的语句,如同咱们在命令行输入语句后敲回车。
学到这里,你们能够稍微喘口气了,由于sed里最经常使用最重要的咱们已经学完了,接下来咱们轻松的学完最后一招-->查看文本
这个功能也是很是得有用,好比咱们想查看文件中的某些行,之前最经常使用的是cat或more或less命令等,但这些命令有些缺点,就是不能查看指定的行。而咱们用了好久的sed命令就有了这个功能了。并且咱们前面也说过使用sed比其余命令vim等读取速度更快!
这里咱们须要用到1个sed命令
“p”:输出指定内容,但默认会输出2次匹配的结果,所以使用-n选项取消默认输出,记忆方法:p的全拼是print,意思是打印。
[root@kaile~]
# sed '2p' person.txt
101,kaile,CEO
102,zhangyang,CTO
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
[root@kaile~]
# sed -n '2p' person.txt
102,zhangyang,CTO
命令说明:选项-n取消默认输出,只输出匹配的文本,你们只须要记住使用命令p必用选项-n。
[root@kaile~]
# sed -n '2,3p' person.txt
102,zhangyang,CTO
103,Alex,COO
命令说明:查看文件的第2行到3行,使用地址范围“2,3”。取行就用sed,最简单
[root@kaile~]
# sed -n '1~2p' person.txt
101,kaile,CEO
103,Alex,COO
105,feixue,CIO
命令说明:打印文件的1,3,5行。~表明步长
[root@kaile~]
# sed -n 'p' person.txt
101,kaile,CEO
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
命令说明:不指定地址范围,默认打印所有内容。
[root@kaile~]
# sed -n '/CTO/p' person.txt
102,zhangyang,CTO
命令说明:打印含CTO的行
[root@kaile~]
# sed -n '/CTO/,/CFO/p' person.txt
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
命令说明:打印含CTO的行到含CFO的行。
[root@kaile~]
# sed -n '2,/CFO/p' person.txt
102,zhangyang,CTO
103,Alex,COO
104,yy,
CFO
命令说明:打印第2行到含CFO的行。
[root@kaile~]
# sed -n '/feixue/,2p' person.txt
105,feixue,
CIO
命令说明:特殊状况,前两行没有匹配到feixue,就向后匹配,若是匹配到feixue就打印此行。因此这种混合地址不推荐使用。
[root@kaile~]
# sed -rn '/kaile|yy/p' person.txt
101,kaile,CEO
104,yy,CFO
命令说明:
使用扩展正则“|”,为了避免使用转义符号“\”,所以使用-r选项开启扩展正则表达式模式
[root@kaile~]
# cat person.txt
101,kaile,CEO
102,zhangyang,CTO
103,Alex,COO
104,yy,
CFO
105,feixue,
CIO
[root@kaile~]
# sed -i.bak 's#zhangyang#NB#g' person.txt
[root@kaile~]
# cat person.txt
101,kaile,CEO
102,NB,CTO
103,Alex,COO
104,yy,
CFO
105,feixue,
CIO
[root@kaile~]
# cat person.txt.bak
101,kaile,CEO
102,zhangyang,CTO
103,Alex,COO
104,yy,
CFO
105,feixue,
CIO
命令行说明:
在-i参数的后边加上.bak(.任意字符),sed会对文件进行先备份后修改
[root@kaile~]
# sed '=' person.txt
1
101,kaile,CEO
2
102,NB,CTO
3
103,Alex,COO
4
104,yy,
CFO
5
105,feixue,
CIO
命令说明:使用特殊符号“=”就能够获取文件的行号,这是特殊用法,记住便可。从上面的命令结果咱们也发现了一个很差的地方:行号和行不在一行。
[root@kaile~]
# sed '1,3=' person.txt
1
101,kaile,CEO
2
102,NB,CTO
3
103,Alex,COO
104,yy,
CFO
105,feixue,
CIO
命令说明:只打印1,2,3行的行号,同时打印输出文件中的内容
[root@kaile~]
# sed '/yy/=' person.txt
101,kaile,CEO
102,NB,CTO
103,Alex,COO
4
104,yy,
CFO
105,feixue,
CIO
命令说明:
只打印正则匹配行的行号,同时输出文件中的内容
[root@kaile~]
# sed -n '/yy/=' person.txt
4
命令说明:只显示行号但不显示行的内容即取消默认输出。
[root@kaile~]
# sed -n '$=' person.txt
5
命令说明:
“$”表明最后一行,所以显示最后一行的行号,变相得出文件的总行数。
方法改进:
[root@kaile~]
# sed '=' person.txt | sed 'N;s#\n# #'
1101,kaile,CEO
2102,NB,CTO
3103,Alex,COO
4104,yy,
CFO
5105,feixue,
CIO
命令说明:前面sed获取文件的行号有一个缺点,咱们这里使用Sed命令N来补偿这个缺点。Sed命令N读取下一行数据并附加到模式空间。
[root@kaile~]
# sed -n '1p;3p;5p' person.txt
101,kaile,CEO
103,Alex,COO
105,feixue,CIO
[root@kaile~]
# sed -n '2,4p;=' person.txt
1
102,NB,CTO
2
103,Alex,COO
3
104,yy,CFO
4
5
命令说明:-n去掉默认输出,2,4p,输出2到4行内容,=输出所有的行的行号
[root@kaile~]
# sed -n '2,4{p;=}' person.txt
102,NB,CTO
2
103,Alex,COO
3
104,yy,CFO
4
命令说明:
‘2,4{p;=}’表明统一输出2,4行的行号和内容
命令说明:删除包含“kaile”的行,就直接用正则匹配字符串kaile便可
模式空间(pattern space):是sed软件从文本读取一行文本而后存入的缓冲区(这个缓冲区是在内存中的),而后使用sed命令操做模式空间的内容。
保持空间(hold space):是sed软件另一个缓冲区,用来存放临时数据,也是在内存中,可是模式空间和保持空间的用途是不同的。Sed能够交换保持空间和模式空间的数据,可是不能在保持空间上执行普通的sed命令,也就是说咱们能够在保持空间存储数据。
下载地址:wget http://sedsed.sourceforge.net/sedsed-1.0 -O /bin/sedsed
sedsed详解:http://aurelio.net/projects/sedsed/
下载调试工具
[root@kaile /]# wgethttp://sedsed.sourceforge.net/sedsed-1.0 -O /bin/sedsed
--2017-04-08 01:28:35-- http://sedsed.sourceforge.net/sedsed-1.0
正在解析主机sedsed.sourceforge.net... 216.34.181.96
正在链接sedsed.sourceforge.net|216.34.181.96|:80... 已链接。
已发出 HTTP 请求,正在等待回应... 301 Moved Permanently
位置:http://aurelio.net/sedsed/sedsed-1.0[跟随至新的 URL]
--2017-04-08 01:28:38-- http://aurelio.net/sedsed/sedsed-1.0
正在解析主机aurelio.net... 208.113.154.67
正在链接aurelio.net|208.113.154.67|:80... 已链接。
已发出 HTTP 请求,正在等待回应... 301 Moved Permanently
位置:http://aurelio.net/projects/sedsed/sedsed-1.0[跟随至新的 URL]
--2017-04-08 01:28:39-- http://aurelio.net/projects/sedsed/sedsed-1.0
再次使用存在的到aurelio.net:80 的链接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:51346 (50K)[text/plain]
正在保存至: “/bin/sedsed”
100%[===================================================================================================================>]51,346 58.3K/s in 0.9s
2017-04-08 01:28:40 (58.3 KB/s) - 已保存 “/bin/sedsed” [51346/51346])
#给它执行权限
[root@kaile /]# which sedsed
/bin/sedsed
[root@kaile /]# chmod +x/bin/sedsed
Usage: sedsed OPTION [-e sedscript] [-fsedscriptfile] [inputfile]
OPTIONS:
-f,--file add file contents to thecommands to be parsed
-e,--expression add the script to thecommands to be parsed
-n,--quiet suppress automaticprinting of pattern space
--silent alias to --quiet
-d, --debug debug thesed script 开启调试工具
--hide hide some debug info (options: PATT,HOLD,COMM)
a |
追加,在指定行后添加一行或多行文本* |
c |
取代指定的行 替换指定行 sed '1c ceshi' test.txt |
d |
删除指定的行* $最后一行 sed '1,5d' 删除一到5行内容 sed '5,$' 删除5到最后一行 |
D |
删除模式空间的部份内容,直到遇到换行符\n结束操做,与多行模式相关 |
i |
插入,在指定行前添加一行或多行文本* |
n |
清空模式空间的内容并读入下一行 |
N |
不清空模式空间,并读取下一行数据并追加到模式空间* |
p |
打印模式空间内容,一般p会与选项-n一块儿使用* |
P(大写) |
打印模式空间的内容,直到遇到换行符\n结束操做 |
q |
退出Sed |
r |
从指定文件读取数据 |
s |
取代,s#old#new#g==>这里g是s命令的替代标志,注意和g命令区分。s命令替换* |
w |
另存,把模式空间的内容保存到文件中 |
y |
根据对应位置转换字符 |
[root@kaile /]# sedsed -d --hide=HOLD -n 'N;2,3p'person.txt
PATT:1$ PATT当前模式空间
COMM:N 执行的命令N不清空模式空间,并读取下一行数据并追加到模式空间*
PATT:1\n2$
COMM:2,3 p 执行的命令:p 打印
1
2
PATT:1\n2$
PATT:3$
COMM:N
PATT:3\n4$
COMM:2,3 p
PATT:3\n4$
PATT:5$
COMM:N
在咱们学习CentOS6系统优化时,有一个优化点:更改ssh服务远程登陆的配置。主要的操做是在ssh的配置文件/etc/ssh/sshd_config加入下面5行文本。(下面参数的具体含义见其余课程。)
Port 52113
PermitRootLogin no
PermitEmptyPasswords no
UseDNS no
GSSAPIAuthentication no
固然咱们可使用vi/vim命令编辑这个文本,可是这样就比较麻烦,如今想用一条命令增长5行文本到第13行前?
注意:修改前别忘了备份配置文件:cp /etc/ssh/sshd_config{,.bak}
上面的命令知识要是不懂请看通配符章节
这道企业面试题能够用咱们学过的sed命令多行追加功能就能够搞定。
第一步备份咱们的ssh 修改配置文件首先须要备份
[root@kaile ~]# cp /etc/ssh/ssh_config/etc/ssh/ssh_config.bak
cp:是否覆盖"/etc/ssh/ssh_config.bak"? y
第二步利用所学sed知识来完成追加
命令
i插入,在指定行前添加一行或多行文本
a 追加,在指定行后添加一行或多行文本
#sed 插入到指定行前添加一行或多行文本
[root@kaile ~]#sed -i '13i Port 52113\nPermitRootLogin no\nPermitEmptyPasswords no\nUseDNSno\nGSSAPIAuthentication no' /etc/ssh/sshd_config
命令说明:题目要求在第13行前插入,那就须要使用命令13i。
#sed追加到指定行后添加一行或多行文本
[root@kaile ~]#sed -i '12a Port 52113\nPermitRootLogin no\nPermitEmptyPasswords no\nUseDNSno\nGSSAPIAuthentication no' /etc/ssh/sshd_config