Blog

测试命令(t)

Content #

测试命令会根据先前替换命令的结果跳转到某个label处,而不是根据address进行跳转。

如果替换命令成功匹配并完成了替换,测试命令就会跳转到指定的标签。如果替换命令未能匹配指定的模式,测试命令就不会跳转。

测试命令的格式:

[address]t [label]

在没有指定label的情况下,如果测试成功,sed会跳转到脚本结尾。

测试命令提供了一种低成本的方法来对数据流中的文本执行基本的if-then语句。如果需要做二选一的替换操作,也就是执行这个替换就不执行另一个替换,那么测试命令可以助你一臂之力(无须指定label): $ sed ‘{s/First/Matched/ ; t > s/Line/Replacement/} > ’ data2.txt Header Replacement Matched Data Line Second Data Replacement End of Data Replacements $ 第一个替换命令会查找模式文本First。如果匹配了行中的模式,就替换文本,而且测试命令会跳过后面的替换命令。如果第一个替换未能匹配,则执行第二个替换命令。

From #

Linux命令行与shell脚本编程大全

用测试命令删除所有的逗号

用分支命令删除所有的逗号

Content #

$ echo “This, is, a, test, to, remove, commas.” | > sed -n {' > :start > s/,//1p > b start > }' This is, a, test, to, remove, commas. This is a, test, to, remove, commas. This is a test, to, remove, commas. This is a test to, remove, commas. This is a test to remove, commas. This is a test to remove commas. ^C $ 脚本的每次迭代都会删除文本中的第一个逗号并打印字符串。这个脚本有一个问题:永远不会结束。这就形成了一个死循环,不停地查找逗号,直到使用Ctrl+C 组合键发送信号,手动停止脚本。

...

分支命令(b)

Content #

分支(b)命令的格式如下:

[address]b [label]

address参数决定了哪些行会触发分支命令。label参数定义了要跳转到的位置。如果没有label参数,则跳过触发分支命令的行,继续处理余下的文本行。

下面这个例子使用了分支命令的address参数,但未指定label: $ cat data2.txt Header Line First Data Line Second Data Line End of Data Lines $ $ sed ‘{2,3b ; > s/Line/Replacement/} > ’ data2.txt Header Replacement First Data Line Second Data Line End of Data Replacements $ 分支命令在数据流中的第二行和第三行处跳过了两次替换命令。

如果不想跳到脚本末尾,可以定义label参数,指定分支命令要跳转到的位置。标签以冒号开始,最多可以有7个字符: :label2 要指定label,把它放在分支命令之后即可。有了标签,就可以使用其他命令处理匹配分支address的那些行。对于其他行,仍然沿用脚本中原先的命令处理: $ sed ‘{First/b jump1 ; > s/Line/Replacement > :jump1 > s/Line/Jump Replacement/} > ’ data2.txt Header Replacement First Data Jump Replacement Second Data Replacement End of Data Replacements $ 分支命令指定,如果文本行中出现了First,则程序应该跳到标签为jump1的脚本行。如果文本行不匹配分支address,则sed编辑器会继续执行脚本中的命令,包括分支标签jump1之后的命令。(因此,两个替换命令都会被应用于不匹配分支 address的行。)如果某行匹配分支address,那么sed编辑器就会跳转到带有分支标签jump1的那一行,因此只有最后一个替换命令会被执行。

...

使用保留空间来反转文本文件的行

Content #

要实现这种效果(先显示最后一行,最后显示第一行),需要利用保留空间做一些特别的铺垫工作。为此,可以使用sed做以下工作。

(1) 在模式空间中放置一行文本。 (2) 将模式空间中的文本行复制到保留空间。 (3) 在模式空间中放置下一行文本。 (4) 将保留空间的内容附加到模式空间。 (5) 将模式空间中的所有内容复制到保留空间。 (6) 重复执行第(3)~(5)步,直到将所有文本行以反序放入保留空间。 (7) 提取并打印文本行。

在使用这种方法时,你不想在处理行的时候打印。这意味着要使用sed的-n选项。然后要决定如何将保留空间的文本附加到模式空间的文本之后。这可以用G命令完成。唯一的问题是你不想将保留空间的文本附加到要处理的第一行文本之后。这可以用感叹号命令轻松搞定:

1!G

接下来就是将新的模式空间(包含已反转的文本行)放入保留空间。这也不难,用h命令即可。将模式空间中的所有文本行都反转之后,只需打印结果。当到达数据流中的最后一行时,你就得到了模式空间的所有内容。要打印结果,可以使用如下命令:

$p

以上是创建可以反转文本行的sed编辑器脚本所需的操作步骤。现在可以运行一下试试: $ cat data2.txt Header Line First Data Line Second Data Line End of Data Lines $ $ sed -n ‘{1!G ; h ; $p }’ data2.txt End of Data Lines Second Data Line First Data Line Header Line $ sed编辑器脚本和预期一样,输出了反转后的文本文件。这体现了保留空间的强大之处。它提供了一种在脚本输出中控制行顺序的简单方法。

注意: 有一个现成的bash shell命令可以实现同样的效果:tac命令会以倒序显示文本文件。你大概也注意到了,这个命令的名字很巧妙,因为它的功能正好和 cat命令相反,所以也采用了相反的命令。

From #

Linux命令行与shell脚本编程大全

...

处理跨行匹配中的最后一行文本(!,N,$)

Content #

$ cat data4.txt
On Tuesday, the Linux System
Admin group meeting will be held.
All System Admins should attend.
$
$ sed 'N;
> s/System\nAdmin/DevOps\nEngineer/
> s/System Admin/DevOps Engineer/
> ' data4.txt
On Tuesday, the Linux DevOps
Engineer group meeting will be held.
All System Admins should attend.
$

由于最后一行进入模式空间后,再执行N命令会出错,从而导致命令

s/System Admin/DevOps Engineer/

并未执行,最后一行没有实现替换。

可以用感叹号来处理数据流中的最后一行文本:

$ sed '$!N;
> s/System\nAdmin/DevOps\nEngineer/
> s/System Admin/DevOps Engineer/
> ' data4.txt
On Tuesday, the Linux DevOps
Engineer group meeting will be held.
All DevOps Engineers should attend.
$

这个例子演示了如何将感叹号与N命令和美元符号($)特殊地址配合使用。美元符号表示数据流中的最后一行,因此当sed编辑器读取到最后一行时,不执行N命令,但会对所有其他行执行N命令。

...

N,P,D模式

Content #

D命令的独特之处在于其删除模式空间中的第一行之后,会强制sed编辑器返回到脚本的起始处,对当前模式空间中的内容重新执行此命令(D命令不会从数据流中读取新行)。在脚本中加入N命令,就能单步扫过(single-step through)整个模式空间,对多行进行匹配。

接下来,先使用P命令打印出第一行,然后用D命令删除第一行并绕回到脚本的起始处,接着N命令会读取下一行文本并重新开始此过程。这个循环会一直持续到数据流结束。

$ cat corruptData.txt
Header Line#
@
Data Line #1
Data Line #2#
@
End of Data Lines#
@
$
$ sed -n '
> N
> s/#\n@//
> P
> D
> ' corruptData.txt
Header Line
Data Line #1
Data Line #2
End of Data Lines
$

数据文件被破坏了,在一些行的末尾有#,接着在下一行有@。为了解决这个问题,可以使用sed将Header Line#行载入模式空间,然后用N命令载入第二行(@),将其附加到模式空间内的第一行之后。替换命令用空值替换来删除违规数据(#\n@),然后P命令只打印模式空间中已经清理过的第一行。D命令将第一行从模式空间中删除,并返回到脚本的开头,下一个N命令将第三行(Data Line #1)文本读入模式空间,继续进行编辑循环。

From #

多行打印命令(P)

Content #

多行打印命令(P)沿用了同样的方法。它只打印模式空间中的第一行,即打印模式空间中换行符及其之前的所有字符。当用-n选项来抑制脚本输出时,它和显示文本的单行p命令的用法大同小异: $ sed -n ‘N ; /System\nAdmin/P’ data3.txt On Tuesday, the Linux System $ 当出现多行匹配时,P命令只打印模式空间中的第一行。该命令的强大之处体现在其和N命令及D命令配合使用的时候。( N,P,D模式)

From #

Linux命令行与shell脚本编程大全

动物之间的社会禁忌

Content #

在进化的过程中,如果动物形成了能致同类于死地的武器,那么这种动物为了生存,就必须形成一种相应的社会禁忌,避免这种武器危及种族的生存。少数猛兽过着非常孤独的生活,它们不需要这种克制。它们只会在交配季节聚到一起,这时性冲动超出了其他所有欲望,包括攻击的欲望。北极熊和美洲虎(Jaguar)就是这样的非社会性动物。因为没有社会禁忌,这些动物如果被关在动物园里,经常会发生同类相残的事情。天生的冲动和禁忌构成了一个系统,再加上自然提供给社会性物种的武器,形成了一个精心设计、自我管理的复合体。所有的生物都通过进化获得了自己的武器,进化的过程也塑造了它们的冲动与禁忌,动物的身体结构和行为系统有机结合,形成了一个整体。

From #

所罗门王的指环

雄鸟和雌鸟的眼神交流方式

Content #

求爱时,雄鸟和雌鸟的眼神交流方式大不相同,十分有趣:雄性寒鸦会用滚烫的眼神直直地看着雌鸟的眼睛,而雌鸟会把眼睛转到其他方向,就是不去看热情的追求者。其实雌鸟也一直在观察雄鸟,它会用几分之一秒的时间快速瞄雄鸟一眼。这几分之一秒足以让她明白,雄鸟的所有古怪动作都是为了赢得它的赞赏;这几分之一秒也足以让“他”知道“她”的想法。如果雌鸟真的不感兴趣,就压根不会去看雄鸟,而年轻的雄性寒鸦就会像任何年轻动物一样,很快放弃自己无谓的努力。面对容光焕发、骄傲地走过来的情郎,雌鸟最终表达了自己的爱意:它在雄鸟面前蹲下,翅膀和尾巴都开始颤抖。双方的动作象征着邀请交配的仪式,不过这些动作并不会走向真正的结合,只是纯粹的欢迎仪式。婚后的雌寒鸦在欢迎丈夫时,也会做出同样的动作,即便当时不是交配季节。系谱学研究中,这种仪式仅仅被赋予了性方面的含义,但在这时,仪式完全与性无关,只是表明妻子对丈夫的顺从。仪式的含义几乎与鱼类的“象征性低级”相同。从未来的新娘顺从雄鸟开始,它开始变得很冷静,并对鸟群中的所有其他成员采取强硬态度。对于雌鸟,签订婚约意味着其在鸟群中的地位得以提升。通常而言,雌鸟都比雄鸟要弱小,雌鸟单身时,地位要比雄鸟的地位低很多。

From #

所罗门王的指环

动物之间的啄序

Content #

动物之间相互认识吗?

尽管有很多著名的动物心理学家怀疑这一点,甚至直接否认这一点,但答案是肯定的。我可以向你保证,我家的任何两只寒鸦,只要看一眼就能认出对方。证据就是它们中间存在等级排序,动物心理学家称之为“啄序”。养家禽的农民都知道,即便是很愚蠢的家禽,它们中间也有严格的等级秩序,每只家禽都敬畏比自己高一级的同类。在经过几次争吵(不一定会打架)后,每只鸟都清楚它要畏惧哪些鸟,哪些鸟要对自己表示尊敬。啄序不仅仅取决于一只鸟的力气,还取决于其勇气、精力,甚至自信心。这种等级制度特别顽固。如果一只动物在与同类的争吵中处于下风,哪怕仅是气势上输了,只要两只动物在同一区域生活,败者就再也不敢轻易在胜者面前放肆。甚至最高等级、最聪明的哺乳动物,也同样如此。我的朋友,已故的图恩·霍恩施泰因(Thun Hohenstain)伯爵曾经养过一只猪尾猴(Nemestrinus Monkey),这只猴子高大魁梧、精力十足,但即便在成年后都从心底里尊敬一只老爪哇猴,这只爪哇猴的块头还不及猪尾猴的一半,只是在猪尾猴小的时候欺压过它。年老的暴君最终会被推翻,这是件极具戏剧色彩的事,而且往往是一场悲剧,尤其在狼群或雪橇犬群中。杰克·伦敦写过一些以北极为背景的小说,里面生动地描述了类似的情景。

From #

所罗门王的指环