sed高级命令

所谓高级,主要是指这里将要提到的命令都能改变sed执行或者控制的流程顺序(sed通常都是一行被读入模式空间,并用脚本中的sed命令一个接一个的应用于那一行)。

高级sed命令分成3个组:

1)处理多行模式空间(N、D、P)。

2)采用保持空间来保存模式空间的内容并使他们可用于后续的命令(H、h、G、g、x)。

3)编写使用分支和条件指令的脚本来更改控制流(:、b、t)。

1、N命令:追加下一行

多行Next(N)命令通过读取当前行的下一行,并把两行拼成一行来进行接下来的处理。

[email protected] 14:04:52 ~
=> cat file
line 1
line 2
line 3
line 4

file文件中的每一行后面都有一个隐藏的换行符”\n”,sed不对每行末尾的”\n”进行处理。

[email protected] 14:04:52 ~
=> sed N file
line 1
line 2
line 3
line 4

经过N处理过的输出和原文件没有区别,但是本质是不一样的。这里sed其实认为自己打印的是2行,第一行为”line 1\nline 2”,而第2行为”line 3\nline 4”,注意这里的2行末尾依然隐藏换行符”\n”,sed依然不处理行尾的”\n”,但是处理行内的”\n”。因为这里默认的动作是打印,所以处理行内的”\n”我们也看不出来。

值得注意的是,处理line 1时,line 2被读入并追加到line 1后面,所以line 1处理完后不再读入line 2(前面已经读过了)而直接读入line 3进行下一个N命令(即读入line 4并追加到line 3后面)。

上面2段如果不理解的话,看下面这个命令:

[email protected] 14:07:04 ~ => sed ‘N;s/\n/ /g‘ file 
line 1 line 2
line 3 lin3 4

这个命令在原来的基础上把行内的”\n”替换成空格了(尽管用了全局替换标志g,sed依然不处理行尾换行符!),看明白N的作用了吗,单独的N可以创建2行模式空间。

 

2、D命令:删除多行模式空间中,直到第一个行内的”\n”为止的所有内容。

D命令通常位于N命令之后,用于处理N命令创建的多行模式空间。D命令删除多行模式空间行内第一个”\n”及其之前的内容后,对余下的内容(第一个行内”\n”之后的内容)重新从sed第一个命令进行处理。

D和d的相同点是,删除内容后,重新从sed第一个命令开始处理,这一点看来D和d都有改变sed执行顺序的能力;区别在于d删除模式空间中的所有内容,然后重新读取文本下一行从sed顶部进行处理,而D删除模式空间的一部分内容,而将模式空间剩下的内容从sed顶部进行处理。

[email protected] 14:09:24 ~
=> sed ‘N;d‘ file
[email protected] 14:09:31 ~
=> sed ‘N;D‘ file
line 4
[email protected] 14:09:43 ~
=>

‘N;d’每次创建2行模式空间,并将模式空间的内容全部删除,所以结果所有4行(sed看来是2行)都删除了。如果file有5行数据,则第5行将被打印出来,因为第5行执行N时读不到下一行了,所以d不执行,打印第5行,你可以自己试一试。

‘N;D’每次创建2行模式空间,删除前面一行,并将模式空间的第2行继续执行’N;D’,直到最后一行N没内容可读,不执行D,而是打印最后一行。’N;D’实际构成了一个循环(想想N直接读入下一行,对2行进行处理,下一次对第2行就不处理了而是读取第3行处理;而加了D之后,先处理2行,再对剩下的第2行接着进行处理)

 

3、P命令:打印模式空间直到第一个”\n”为止的所有内容。

p(小写)是打印模式空间的所有内容,P(大写)是打印模式空间的一部分,这一区别和D/d类似。有一点要注意,不要把任何命令放在d或者D后面,因为那样该命令永远也没有执行的机会了。例如sed ‘N;D;P’ file和sed ‘N;D’ file是完全相同的效果。

[email protected] 14:12:05 ~
=> cat file
line 1 li
cong line 2
line 3 licong
line 4 li
cong line 5

我们要把分在两行的li和cong合到一行应该怎么做呢?

[email protected] 14:12:09 ~
=> sed ‘N;s/li\ncong */licong\n/g;P;D‘ file
line 1 licong
line 2
line 3 licong
line 4 licong
line 5

执行这个sed命令的流程是这样的:

① 首行文本应用N读取下一行,构成2行模式空间

   line 1 li\n

   cong line 2

   s命令将li\ncong (注意cong后有一个空格)替换成licong\n,即

   line 1 licong

   line 2

   接着执行P,打印line 1 licong(P结束后两行模式空间没有改变)

   再对两行模式空间执行D,删除line 1 licong\n,并将剩下的line 2做为新的模式空间从头执行sed命令;

② 对模式空间内容line 2先执行N,读取下一行line 3 licong,创建两行模式空间

    line 2

    line 3 licong

   这次s没找到匹配内容,所以执行s后面的P;D命令,重新打印、删除,进行下一轮循环;

   。。。

③ 最后一行line 5执行N没有内容可读,直接打印该行。

 

4、h、H、g、G、x这几个命令都是用于模式空间和保持空间转换的。这里有必要解释一下模式空间和保持空间了:

模式空间——容纳当前输入行的缓冲区。

除了h/H/g/G/x,其他所有sed命令都是针对模式空间的内容进行处理的!

保持空间——模式空间以外的一个预留缓冲区。

只有h/H/g/G/x命令可以访问到保持空间的内容,并用于与模式空间内容的转换。

h:将模式空间的内容复制到保持空间,类似与重定向符号>,会覆盖原由保持空间内容

H:将模式空间的内容追加到保持空间,类似与追加重定向>>,追加到保持空间的尾行下

g:类似h,将保持空间的内容复制到模式空间

G:类似H,将保持空间的内容追加到模式空间

x:交换模式空间与保持空间中的内容 

[email protected] 14:17:40 ~
=> cat file
1
2
11
22
[email protected] 09:29:59 ~
=> sed ‘/1/{h;d};/2/G‘ file
2
1
22
11

这个sed命令完成了反转的功能,我们来看看是怎么实现的:

① /1/{h;d}命令搜索模式空间包含1的行然后先后执行h和d命令。结果首行1将被应用,h把该行(内容为1)复制到保持空间,此时模式空间和保持空间中的内容为:

   模式空间:1

   保持空间:1

   接着执行d,d不能访问保持空间,只处理模式空间的内容,将模式空间的内容删除,此时:

   模式空间: (空,没有内容)

   保持空间:1

② d命令执行完之后,执行/2/G,即在模式空间搜索包含2的行进行G处理,而此时模式空间无内容,所以不做任何操作。

③ 读取下一行文本到模式空间,继续执行’/1/{h;d};/2/G’。下一行文本的内容是2,此时:

   模式空间:2

   保持空间:1

   与步骤二的道理相同,h、d得不到执行(因为模式可空间没找到包含1的行);而’/2/G’将被执行,将保持空间的内容追加到模式空间后面,此时:

   模式空间:2

   1

   保持空间:1

   这一步完成以后,模式空间的内容将被sed默认地打印出来(如果有-n参数才不打印),于是前两行处理完之后,将输出:

   2

   1

   同理,后两行处理完之后,将输出:

   22

   11

   于是,我们看到了最后的结果:

   2

   1

   22

   11

这个最简单的例子有很多地方值得挖掘,我们就来看看最重要的几点:

1)当sed后面带有一个以上的命令时,它的处理顺序是这样的:一次读入一行到模式空间,然后将所有的命令应用于该行;而不是一次将一个命令作用与所有行;

2)当某个条件后面有{}时,{}里面的命令依次作用于满足该条件的行;

3)h/H/g/G命令操作缓冲区时,都会在目的缓冲区后加一个换行(即使该缓冲区无内容),然后复制或追加源缓冲区内容在该换行符之后;

4)没有使用-n参数时,当一行执行完所有命令后,sed会默认打印最终模式空间中的内容;

如果使用-n参数,只有应用了p/P命令的模式空间内容才会被打印出来。

 

5、x命令暂不举例,我们来看看最后一组高级命令(:、b、t)

分支(b)和测试(t)命令几乎可以任意改变sed命令的执行顺序,他们都将sed转移到包含标签的行,如果没有指定标签,则将转移到命令末尾。b用于无条件的转移(即一碰到b立刻转移);t用于有条件转移,只有当替换命令改变当前行时才会执行。

标签定义:

:lable

lable可以随便用什么名字,自己能方便看明白就行;冒号和标签之间不允许有空格,lable后面如果有空格将被认为是lable的一部分(不建议在lable后面带空格)

b和t的用法:

[address]b [lable]

[address]t [lable]

b/t和lable之间有空格,但lable后面不要插入空格。

举例:

[email protected] 09:35:57 ~
=> cat file
line 1 li
cong line 2
line 3 licong
line 4 li
cong line 5
[email protected] 09:36:00 ~
=> sed -n ‘$!{/licong/!{h;N;D}
> x;G;N;p;b
> }
> ${/licong/{x;G;p}}‘ file
cong line 2
line 3 licong
line 4 li

这个sed命令的功能是寻找包含字符串licong的行,并打印该行及其前后一行。这个命令并不完善,它不能很好的处理第一行匹配的情况,加入该功能命令会变得更复杂。我们来解释一下上面的结果是怎么来的。

sed -n ‘$!{/licong/!{h;N;D}

   x;G;N;p;b

   }

对除末行以外的所有行($!的作用),执行/licong/!{h;N;D};x;G;N;p;b

/licong/!{h;N;D}

   对不包含字符串licong的行依次执行h;N;D,第一行line 1 li不包含licong,于是执行:

   把该行复制到保持空间,读取追加下一行,此时

   模式空间:line 1 li

   cong line 2

   保持空间:line 1 li

   再对模式空间执行D,并接着从头处理新的模式空间,此时

   模式空间:cong line 2

   保持空间:line 1 li

从头对模式空间的内容cong line 2执行$!{/licong/!{h;N;D},此时的模式空间依然不包含licong,所以进行一二两步同样的操作,结束后:

   模式空间:line 3 licong

   保持空间:cong line 2

④ 再从头对新的模式空间line 3 licong执行/licong/!{h;N;D};x;G;N;p;b。因为此时的模式空间包含licong,所以不执行h;N;D了,而是执行x;G;N;p;b。x用与交换模式空间和保持空间的内容,交换的结果是:

   模式空间:cong line 2

   保持空间:line 3 licong

   接下来执行G,将保持空间的内容追加到模式空间之后:

   模式空间:cong line 2

   line 3 licong

   保持空间:line 3 licong

   再执行N,将下一行读取追加到模式空间之后:

   模式空间:cong line 2

   line 3 licong

   line 4 li

   保持空间:line 3 licong

   再执行p,打印模式空间的内容:

   cong line 2

   line 3 licong

   line 4 li (这就是我们看到的结果)

   之后还有一个b,就是跳过b后面的命令,再读下一行。命令最后一部分${/licong/{x;G;p}}是用来处理最后一行的,如果最后一行包含licong则打印该行很上面一行(而不打印下一行,因为没有N命令)

 

到此,sed的高级命令就介绍完了。《sed&awk》第二版有一句话:“一旦你理解了这里所给出的命令,那么就可以认为自己是真正的sed的主人了。”

再总结一下sed所有的功能,总的来说还是替换命令’[address]s/source/replace/flag’最常用,而高级命令则用于完成复杂的任务;还有sed的-n(抑制默认输出)、-i(更改原文件)等参数也很常用。

 

转载自:http://licong.blog.51cto.com/542131/204226

 

———— Weiyan Shen.2015.02.13.

时间: 2024-10-25 18:22:43

sed高级命令的相关文章

linux:sed高级命令之n、N(转)

sed的语法格式: sed [option] {sed-command} {input-file} sed在正常情况下,将处理的行读入模式空间(pattern space),脚本中的“sed-command(sed命令)”就一条接着一条进行处理,知道脚本执行完毕.然后该行呗输出,模式(pattern space)被清空:接着,在重复执行刚才的动作,文件中的新的一行被读入,直到文件处理完毕. 但是,由于种种原因,如用户希望在某个条件下,脚本中的某个命令被执行或希望模式空间(pattern spac

sed高级命令小记

sed高级命令: g: 将hold space中的内容拷贝到pattern space中,原来pattern space里的内容被覆盖 G:将hold space中的内容append到pattern space\n后 h: 将pattern space中的内容拷贝到hold space中,原来hold space里的内容被覆盖 H: 将pattern space中的内容append到hold space\n后 d: 删除pattern中的所有行,并读入下一新行到pattern中 [[email 

sed高级命令及模式空间和交换空间简介

高级命令 之前我们用到的sed命令都是一行一行的进行处理文本的,不过有些时候单行处理可能并不能满足我们的需要,所以sed还提供了多行模式,多行模式的命令主要有NPD这三个,N:读取匹配到的行的下一行追加至模式空间P:打印模式空间开端至\n内容,并追加到默认输出之前D:如果模式空间包含换行符,则删除直到第一个换行符的模式空间中的文本, 并不会读取新的输入行,而使用合成的模式空间重新启动循环.如果模式空间 不包含换行符,则会像发出d命令那样启动正常的新循环首先还是先看一下N命令的大致流程图,P和D命

字符及文本处理之sed:sed使用高级命令

三.sed高级编辑命令      t,T,D,P,n,N,H,h,g,G 前面的基本用法已经可以满足基本应用,但sed还有一些高级用法(装X利器),要学习sed高级命令首先要理解清楚sed的另一个缓冲区"保持空间". 前面基本用法中也有提到模式空间,即为处理文件中一行内容的一个临时缓冲区.处理完一行之后就会把模式空间中的内容打印到标准输出,然后自动清空缓存. 而这里说的保持空间是sed中的另外一个缓冲区,此缓冲区正如其名,不会自动清空,但也不会主动把此缓冲区中的内容打印到标准输出中.而

vi/vim高级命令集粹

vi/vim高级命令集粹 (ctrl +v过来 留着以后看) 1.交换两个字符位置 xp 2.上下两行调换 ddp 3.把文件内容反转 :g/^/m0/ (未通过) 4.上下两行合并 J 5.删除所有行 dG 6.从当前位置删除到行尾 d$ 7.从当前位置复制到行尾 y$ 如果要粘贴到其他地方 p 就可以了 由于vi 是建立在 EX 上的 所以 当键入 : 时就来到了 EX 命令状态 8.:ab string strings 例如 ":ab usa United States of Americ

sed和awk之sed篇(含sed高级用法)

(原创文章,谢绝转载~) sed(stream editor)和 awk 是linux环境下处理文本.数据的强大"利器",sed对数据列的处理稍逊,awk则更似一门语言,control flow的语法基本和c语言一样,能够处理复杂的逻辑,二者经常配合正则表达式使用.本文简述sed用法. sed对输入流(文本数据)逐行处理,其基本格式为: sed (OPTIONS...) [SCRIPT] [INPUTFILE...]#examplessed '10d' test.txtsed -i '

Linux网卡高级命令、IP别名及多网卡绑定 转

http://www.cnblogs.com/xiaoluo501395377/archive/2013/05/26/3100065.html 本篇随笔将详细讲解Linux系统的网卡高级命令.IP别名以及Linux下多网卡绑定的知识 一.网卡高级命令 在之前的一篇随笔里Linux学习之CentOS(九)--Linux系统的网络环境配置,详细讲解了Linux系统下的网络环境配置等知识,我们了解了一些关于网络配置的一些基本命令.在这里将补充一些Linux系统下有关网卡的一些高级命令. ①mii-to

你需要知道的12个Git高级命令

众所周知,Git目前已经是分布式版本控制领域的翘楚,围绕着Git形成了完整的生态圈.学习Git,首先当然是学习Git的基本工作流.相比于SVN等传统版本控制系统来说,Git是专为分布式版本控制而生的强大工具.使用Git时常用的命令有pull.commit.push等,貌似很简单.不过,有时你会遇到合并冲突的情况,Git这时会将冲突标记出来,需要你手工来解决.有时,你会不小心将代码提交到错误的分支上,并且又推送到了远程仓库.还有些时候,你需要切换到不同的分支,但Git却不让你这么做,因为还有未保存

【Linux 高级命令】

20个对Linux专家非常有用命令 http://os.51cto.com/art/201308/406979_all.htm 13个超实用的Linux性能监测命令行工具 http://os.51cto.com/art/201304/388673_all.htm 11 个很有用但鲜有人知的 Linux 命令 http://os.51cto.com/art/201310/414075.htm [Linux 高级命令],布布扣,bubuko.com