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

高级sed命令分成3个组:

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

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

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

1、N命令:追加下一行

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

shenweiyan@localhost 14:04:52 ~
=>

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

shenweiyan@localhost 14:04:52 ~
=>

经过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段如果不理解的话,看下面这个命令:

shenweiyan@localhost 14:07:04 ~ => sed 'N;s/\n/ /g' file 
 line
line  lin3 

这个命令在原来的基础上把行内的”\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顶部进行处理。

shenweiyan@localhost :: ~
=> sed 'N;d' file
shenweiyan@localhost :: ~
=> sed 'N;D' file
line
shenweiyan@localhost :: ~
=>

‘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是完全相同的效果。

shenweiyan@localhost :: ~
=> cat file
line  li
cong line
line  licong
line  li
cong line 

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

shenweiyan@localhost :: ~
=> sed 'N;s/li\ncong */licong\n/g;P;D' file
line  licong
line
line  licong
line  licong
line 

执行这个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:交换模式空间与保持空间中的内容

shenweiyan@localhost :: ~
=> cat file 
shenweiyan@localhost :: ~
=> sed '/1/{h;d};/2/G' file 

这个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后面不要插入空格。

举例:

shenweiyan@localhost :: ~
=> cat file
line  li
cong line
line  licong
line  li
cong line 
shenweiyan@localhost :: ~
=> sed -n '$!{/licong/!{h;N;D}
> x;G;N;p;b
> }
> ${/licong/{x;G;p}}' file
cong line
line  licong
line  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.

sed高级命令的更多相关文章

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

    sed的语法格式: sed [option] {sed-command} {input-file} sed在正常情况下,将处理的行读入模式空间(pattern space),脚本中的“sed-comm ...

  2. vi/vim高级命令集粹

    vi/vim高级命令集粹 (ctrl +v过来 留着以后看) 1.交换两个字符位置 xp 2.上下两行调换 ddp 3.把文件内容反转 :g/^/m0/ (未通过) 4.上下两行合并 J 5.删除所有 ...

  3. sed修炼系列(三):sed高级应用之实现窗口滑动技术

    html { font-family: sans-serif } body { margin: 0 } article,aside,details,figcaption,figure,footer,h ...

  4. 【转】sed 高级用法

    首先,应该明白模式空间的定义.模式空间就是读入行所在的缓存,sed对文本行进行的处理都是在这个缓存中进行的.这对接下来的学习是有帮助的. 在正常情况下,sed将待处理的行读入模式空间,脚本中的命令就一 ...

  5. sed高级用法:模式空间(pattern space)和保持空间(hold space)

    摘自:https://blog.csdn.net/ITsenlin/article/details/21129405 sed高级用法:模式空间(pattern space)和保持空间(hold spa ...

  6. sed 常用命令 网址

    https://wangchujiang.com/linux-command/c/sed.html https://linux.cn/article-11367-1.html https://juej ...

  7. Git / 程序员需要知道的12个Git高级命令

    众所周知,Git目前已经是分布式版本控制领域的翘楚,围绕着Git形成了完整的生态圈.学习Git,首先当然是学习Git的基本工作流.相比于SVN等传统版本控制系统来说,Git是专为分布式版本控制而生的强 ...

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

    http://www.cnblogs.com/xiaoluo501395377/archive/2013/05/26/3100065.html 本篇随笔将详细讲解Linux系统的网卡高级命令.IP别名 ...

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

    众所周知,Git目前已经是分布式版本控制领域的翘楚,围绕着Git形成了完整的生态圈.学习Git,首先当然是学习Git的基本工作流.相比于SVN等传统版本控制系统来说,Git是专为分布式版本控制而生的强 ...

随机推荐

  1. Lua编译

    编译lua包含3部分内容:lua库文件(lua*.lib),lua解释器(lua.exe),lua编译器(luac.exe) 首先: 下载源代码,编译批处理(以5.2.3为例): cd srccl / ...

  2. ASP.NET MVC Json() 处理大数据异常解决方法 json MaxJsonLength

    网上很多解决方案,在webconfig中添加,但是实践证明无效 <system.web.extensions> <scripting> <webServices> ...

  3. Windows 下 Apache HTTP Server 安装、配置以及与 Tomcat 的整合(附图)

    如果您能点开这篇文章,说明您已对熟悉Apache HTTP Server(下文用Apache简称)配置的重要性已很清楚了,本文不在赘述,直接介入正题,请往下阅读: 为便于阅读,列出文章目录: 一.Ap ...

  4. js监控视频播放的事件并打印log

    html代码: <!DOCTYPE html> <html> <head> <meta http-equiv="content-type" ...

  5. MEMS加速度计工作原理

    一般加速度计有两块芯片组成,一块是MEMS传感器,另一块是客户化的信号处理芯片. 加速度计也称惯性传感器,因为它的工作原理就是靠MEMS中可移动部分的惯性.由于中间电容板的质量很大,而且它是一种悬臂构 ...

  6. Windows提供了两种将DLL映像到进程地址空间的方法

    调用DLL,首先需要将DLL文件映像到用户进程的地址空间中,然后才能进行函数调用,这个函数和进程内部一般函数的调用方法相同.Windows提供了两种将DLL映像到进程地址空间的方法: 1. 隐式的加载 ...

  7. cf468A 24 Game

    A. 24 Game time limit per test 1 second memory limit per test 256 megabytes input standard input out ...

  8. 如何用SQL SERVER 2005连接SQL SERVER 2008

    原先使用sql server 2005数据库,后来由于工作需要升级为sql server 2008 开发版,升级过程很简单,基本没有什么问题 下面主要说说,如何使用sql server 2005 st ...

  9. Javascript 中的false,零值,null,undefined和空字符串对象

    在Javascript中,我们经常会接触到题目中提到的这5个比较特别的对象--false.0.空字符串.null和undefined.这几个对象很容易用错,因此在使用时必须得小心. 类型检测 我们下来 ...

  10. the first has precedence, perhaps you need a NameVirtualHost directive

    报错信息1: Starting httpd: [Fri May 19 11:49:42 2011] [warn] VirtualHost 127.0.0.1:80 overl aps with Vir ...