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

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

文章分类

全部博文(272)

文章存档

2015年(2)

2014年(5)

2013年(25)

2012年(58)

2011年(182)

分类: LINUX

2011-08-03 10:35:20

1)
[user_0001]
ID=1
Serverid=102
name="1234"
[Server_000017]
ID=102
RealID=19
ServerType=2
MainType=2
[user_0002]
ID=2
Serverid=103
name="5678"
 
想提取出匹配RealID的那个段落,长度内容不完全确定,不能按行来取:
[Server_000017]
ID=102
RealID=19
ServerType=2
MainType=2
 
  1. awk -vRS='\\[[^]]*]\n' -vORS= '/RealID/{print T$0}{T=RT}' file
  2. awk -vRS="\\\[[^]]*]\n" -vORS= '/RealID/{print T$0}{T=RT}' file

[解析]

  首先我们要分析文本,既然这个段落的行数不确定,等于说要提取关键字的上几行和下几行,这个是无法预料的,所以我们必须配置RS来达到分割该段落的目的,很明显大家注意到了每个段落的起始都是[.*]这样的形式,那么我们把它作为RS分割符不就可以了吗?找定了方向就开始匹配,发现对][符号的转义awk频繁报错,最后在黑哥的指点下才搞定了它:'\\[[^]]*]\n',红色部分才是对]符号完成了转义,]符号其实是不需要转义的。绿色部分才是正则的字符集,还要注意的是单引号引起来的,双引号就是第2个语句的写法,记不住的就死背吧。大家特别注意[Server_000017]是上一个段落的RS分割符,所以在匹配关键字之前就把它赋值给一个变量,以免动态匹配的RT把它给替换了。再把ORS设置一下,因为它默认是换行的,末尾会多出一个空行来。


  1. sed -n '1h;/\[/!{1!H;$!b};x;/RealID/p' file

[解析]

第一行把内容拷贝到hold space,原因是 H 追加的话首行会是空行,然后匹配到 [ 标签符号就不会执行花括号里的操作,如果没匹配到呢就把该行 H 追加到 hold space 中,最后一行不 b ,因为跳了就没有下一个 [ 标签符号来激活了。然后 x 把两个空间的内容交换,看是否匹配到我们所要的关键字,如果匹配到就打印。


  1. sed -n ':a;N;s/\(RealID.*\)\n\[.*/\1/p;t;s/.*\[/[/;$!ba;/RealID/p' file

[解析]

这是 :a;N 的搭配,N读取下一行,尝试去匹配到 RealID 替换掉 N 读上来的下一行的标签,然后打印,替换成功后就t跳转到命令结束处,然后匹配一直 N 读取下一行,没匹配替换到关键字的话,就尝试去把上个段落的内容替换掉,这样就等于删除了上个没匹配到关键字的段落了。不是最后一行就跳转,这里要加上关键字的匹配打印,否则到了末行要是没有我们需要的段落,它也会 p 打印出来,最后加个 p 的意思是,如果我们的段落是最后的话,末行结束后把它要输出。这里加个关键字的匹配打印,是为了限制其他非匹配内容打印出来。



2)

文本:

[common]

conf_1 = a/a.cfg

[test1:test1]

conf_0 = b/a.ini

conf_0 = c/b.ini

conf_1 = d/c.conf

conf_232323 = e/test.a

[test1:test2]

conf_0 = d/1.ini


求出匹配 [test1:test1] 下的所有行,截止到下个[]出现:

[test1:test1]

conf_0 = b/a.ini

conf_0 = c/b.ini

conf_1 = d/c.conf

conf_232323 = e/test.a


  1. awk -vRS='\\[[^]]*]\n' 'RT~/test1:test1/{j=RT;getline i;printf j i}' file

[解析]

先对 [ 转义,然后设定为RS分隔符,当RT匹配到需要的字样的时候,把RT给一个变量保存,然后getline读取下一行(其实就是下个段落的内容)给变量i,最后打印匹配的段落分割符和下一行的内容,这个语句的关键地方是把RT在读取下一行之前就把它保存给一个变量,否则读取下一行时,RT就会跟随下一行的RS发生变化。


  1. sed -n '1h;/\[/!{1!H;$!b};1!{x;/test1:test1/p}' file

[解析]

这个例子和上个梢有不同,它是匹配标签,而上个例子是匹配标签段落里内容,因为第一行就是 [ 开头的,所以 x 交换的语句要排除第一行,就这一点区别。


  1. sed -n '/test1:test1/{:a;N;/\n\[/!{$!ba};s/\n\[.*//;p}' file

[解析]

这儿呢 :a;N;ba 的组合没那么好使,因为它老要去把下一行的 [标签] 读出来,无奈只好替换了。


  1. sed -n '/test1:test1/{:a;p;n;/]/!ba}' file

[解析]

这才是王道,我们不用 N 了,用 n 。首先把匹配到关键字标签的行打印,然后 n 移到下一行,看是否匹配标签的符号,如果没匹配就跳转,又打印该行,再 n 读取下一行,如果是最后一行,照样跳转去标签处,p 打印出内容,再 n 的时候,注意这是 GNU sed 的特点,当没有下一样读取和操作时,会中止整个命令,后面的命令不再运行,这样就避免了后面的 ba 死循环。N 同样有这个特性。


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