Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3020578
  • 博文数量: 272
  • 博客积分: 5544
  • 博客等级: 大校
  • 技术积分: 5496
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-08 00:48
个人简介

  每个人都要有一个骨灰级的爱好,不为金钱,而纯粹是为了在这个领域享受追寻真理的快乐。

文章分类

全部博文(272)

文章存档

2015年(2)

2014年(5)

2013年(25)

2012年(58)

2011年(182)

分类: LINUX

2011-11-05 10:06:21

文本:
  1. [11111]
  2. kk=11
  3. aaa=111
  4. [22222]
  5. kk=22
  6. aaa=222
  7. aaa=xxx
  8. aaa=xxx
  9. [33333]
  10. kk=33
  11. aaa=333
所谓的段落,就是一个[xxx]标签到下个标签之前的内容,我们要替换段落[22222]里的第二个aaa后面的值,这里特别注意段落[22222]可能出现在文本中的任意位置。段落里的内容也是不固定的。所以不能按照固定的行,或前后特征来判断,唯一的两个条件就是段落标签[22222],和该段落内出现第二个aaa替换后面的内容为TEST:
  1. [11111]
  2. kk=11
  3. aaa=111
  4. [22222]
  5. kk=22
  6. aaa=222
  7. aaa=TEST
  8. aaa=xxx
  9. [33333]
  10. kk=33
  11. aaa=333




  1. sed -n '1h;/\[/!{1!H;$!b};1!{x;/\[22222\]/s/\(aaa=\)[^\n]*/\1TEST/2;p}' file
[解析]
按我们以前讲过的,用 h 和 H 搭配,把文本读入 hold space 中,不是最后一样的话都 b 跳转去行末,等于说跳过后面的命令(主要是避开后面的 p 打印)。当匹配到下个段落的标签时,就把两个空间的内容交换,再看现在 pattern space 里的内容是否匹配 [22222] 标签,如果匹配就把 aaa= 标记,替换第两个,最后再把该段落打印出来。




  1. sed '/\[22222]/{:a;N;s/\(aaa=\)[^\n]*/\1TEST/2;t;/\n\[/!ba}' file

  2. sed '/\[22222]/{:a;N;/\n\[/!{$!ba};s/\(aaa=\)[^\n]*/\1TEST/2}' file
[解析]
这是:a;N;ba搭配的用法,因为文本是全部会打印的,所以没必要 -n 参数再 p 打印,前面不匹配到标签的一律放过,直到匹配到 [22222] 标签后,开始 N 读取下一行,然后尝试替换第2个 aaa= 内容,如果不成功则 t 跳转不会生效。如果没有替换成功的话再看是否匹配 /\n\[/ 如果匹配到就不会跳转去 :a 标签处,这么做的用意在于当[22222]段落中的 aaa 数量没有达到两个,不满足替换的时候,为了防止继续往下读,把 [33333] 标签中的第一个 aaa 读取进入 pattern space 里凑足了两个 aaa 结果给替换了, t 跳到命令末尾,结束了循环。这样就存在了漏洞,所以在跳转的地方必须加上判断,一定要注意排除下一个特征的情况,否则不跳出这个循环会读取下一个段落的
第二个命令比第一个略长一点,但是从效率上讲要略微高一点点,以为它不用每次 N 读去下一行的时候就起尝试替换一次,而它是循环一直读到下一个标签或者最后一行才中止,统一进行一次性替换,替换掉第二个aaa后面的值。







  1. awk -vRS='\\[[^]]+]\n' 'i~/\[22222]/{$0=gensub("(aaa=)[^\n]*","\\1nnn",2)}{printf i $0;i=RT}' file
[解析]
把标签通过正则设定为RS,把上一个RT保存给变量,然后匹配后一个段落,替换思路和sed是一样的。


  1. awk '/\[22222]/{f=1;print;next}f{if(/aaa/&&++i==2)$0="aaa=TEST"}/\[/{f=0}1' file
[解析]
这是用的变量开关,允许我这样叫它,因为只有匹配到[22222]时才会把这个开关打开。然后通过变量i来记数,当它等于2时才执行这个替换。然后匹配到下一个标签时,则关闭这个变量开关。



阅读(7009) | 评论(2) | 转发(1) |
给主人留下些什么吧!~~

iamqilei2016-06-24 20:50:47

确实是sed专家级。我觉得复杂一些的,还是用perl写的程序更容易理解。

linux_kaige2011-11-06 22:53:49

至今没发现有比你对sed理解更深刻的人了