Sed 命令地址匹配问题总结

这个问题来源于ChinaUnix的一篇帖子“sed地址和模式匹配的问题”。

man sed手册说明

Sed默认的命令执行范围是全局的,如果想仅对其中部分行执行命令,可以使用地址限制。在Manual手册中有一节关于地址的描述,摘取部分如下:

Sed commands can be given with no addresses, in which case the command will be executed for all input lines;

Sed默认是全局编辑的,因此如果不明确指定行的话,命令会在所有输入行上执行。

with one address, in which case the command will only be executed for input lines which match that address;

如果指定一个行地址,那么sed命令就限制在那一行执行。

or with two addresses, in which case the command will be executed for all input lines which match the inclusive range of lines starting from the first address and continuing to the second address.

如果给了两个地址,即地址对(或者地址范围),则命令在匹配的这个地址范围内执行。但是需要注意的几点是:

The syntax is addr1,addr2 (i.e., the addresses are separated by a comma); the line which addr1 matched will always be accepted, even if addr2 selects an earlier line; If addr2 is a regexp, it will not be tested against the line that addr1 matched.

上面的内容,大致意思是说:(a)

对于像“addr1,addr2”这种形式的地址匹配,如果addr1匹配,则匹配成功,“开关”打开,在该行上执行命令,此时不管addr2是否匹配,即使addr2在addr1这一行之前;

接下来读入下一行,看addr2是否匹配,如果addr2在addr1之前,则不匹配,不执行命令,关闭“开关”;如果addr2匹配,则执行命令,同样开关“关闭”;如果addr2在addr1之后,则一直处理到匹配为止,换句话说,如果addr2一直不匹配,则开关一直不关闭,因此会持续执行命令到最后一行。

After the address (or address-range), and before the command, a ! may be inserted, which specifies that the command shall only be executed if the address (or address-range) does not match.

如果地址或者地址对之后有一个"!",表明对匹配的行不执行后面的命令,刚好相反。

地址形式

Sed一般至少支持以下形式的地址表示:

number: 这一种情况不多说。

first~step: 从first行开始,每隔step行执行一次命令。详细的内容也可以参照手册:

Match every step’th line starting with line first. For example,‘sed -n 1~2p’ will print all the odd-numbered lines in theinput stream, and the address 2~5 will match every fifth line, starting with the second. (This is an extension.)

/regexp/: 同第一种方法类似,不过是匹配该正则的那一行。

在匹配行的时候,$是特殊的标记,匹配最后一行。1匹配第一行,而不是^,这点和正则不大一样。

另外,GNU Sed还支持以下几种特殊的地址对形式:(平常使用的基本是GNU Sed,即gsed)

0,addr2

这种形式的地址对,默认第一个地址是匹配的,也就是匹配开关打开,直到找到匹配addr2的那行为止,匹配开关关闭。大多数情况下和1, addr2是一样的,除非addr2匹配文件的第一行,在这种时候,0, addr2就在第一行就关闭了,而1, addr2会继续往下找匹配的行。

Start out in "matched first address" state, until addr2 is found. This is similar to 1,addr2, except that if addr2 matches the very first line of input, the 0,addr2 form will be at the end of its range, whereas the 1,addr2 form will still be at the beginning of its range.

可以看一个例子:

$ seq6|sed-n'0, /1/p'# 打印第一行(/1/是正则表达式,因为第一行的内容是1)

为什么不相同呢? 解释一下:

0, addr2 这种形式默认第一个地址是匹配的,然后直到add2匹配为止。因此上述情况,只要看每一行是否匹配第二个地址就可以了addr2,因为第一行是匹配的,所以打印到第一行为止。

1, addr2 这种形式就是普通形式,参考(a)红字说明部分,不管addr2匹配与否,第一行是匹配的,然后读入第二行,发现不匹配addr2,继续读,直到最后也没找到匹配,因此打印从第1行到最后一行之间的所有内容。

但是这种地址对表示有一个限制,即addr2只能使用/regex/形式,如果使用行号,就会出错,不信可以试试。

addr1,+N: 从匹配的addr1行开始,连续N行,当然包括addr1这一行。

addr1,~N: 从匹配的addr1行开始,直到某一行,该行的行号是N的倍数为止。

总结

可以总结出几个关键点:

地址对addr1, addr2的匹配方式 ,从匹配addr1的那行开始,打开匹配开关,直到匹配addr2的那行结束,关闭匹配开关,之后的行会忽略这个地址对,不再做匹配。(b)

地址对addr1, addr2的匹配方式 ,假设addr1是number,即行号,如果新读入行的行号大于addr1,则匹配;小于addr1,则不匹配。(c)

注意:如果addr2是行号,如果新读入行的行号小于addr2,则匹配,继续往下读;大于addr2,则不匹配,关闭匹配开关。刚好与上面的情况相反(这个比较好理解,可以辅助记住(c)这种情况)。

最后引用chinaunix上的那个帖子的问题,以下两种情况结果为什么会不一样:

$ seq6|sed'1,2d'|sed'1,2d'# 结果返回5 6$ seq6|sed-e'1,2d'-e'1,2d'# 结果返回4 5 6

显然这两种情况使用sed的命令形式是不一样的,第一种利用管道使用了sed两次,结果返回5 6,没什么问题;第二种情况在同一个sed命令中使用了两次1,2d,按常理应该是返回 3 4 5 6,结果返回 4 5 6,第3行竟然也被意外地删除了,为什么呢?

解释:

首先第一行被读入,遇到第一组expression -> 1, 2d,第一行匹配成功(打开匹配开关),执行d命令,d命令清空模式空间的内容,因此不会再执行接下来的命令。

继续从标准输入读入第二行,同1

读入第三行,第一组expression匹配失败(因为3>2),因此试着执行第二组expersson->1,2d,因为3>1,打开匹配开关,执行d。(这里是关键)

读入第四行,执行第二组expersson->1,2d,因为4>2,匹配失败,关闭匹配开关,同时也不执行d。

因此,最后第1 2 3行被删除。

转自:团子的小窝, 本文固定链接:Sed 命令地址匹配问题总结

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容