分类:
2012-05-19 23:04:23
原文地址:awk之 [ 符号的转义和对段落的操作 作者:zooyo
[解析]
首先我们要分析文本,既然这个段落的行数不确定,等于说要提取关键字的上几行和下几行,这个是无法预料的,所以我们必须配置RS来达到分割该段落的目的,很明显大家注意到了每个段落的起始都是[.*]这样的形式,那么我们把它作为RS分割符不就可以了吗?找定了方向就开始匹配,发现对][符号的转义awk频繁报错,最后在黑哥的指点下才搞定了它:'\\[[^]]*]\n',红色部分才是对]符号完成了转义,]符号其实是不需要转义的。绿色部分才是正则的字符集,还要注意的是单引号引起来的,双引号就是第2个语句的写法,记不住的就死背吧。大家特别注意[Server_000017]是上一个段落的RS分割符,所以在匹配关键字之前就把它赋值给一个变量,以免动态匹配的RT把它给替换了。再把ORS设置一下,因为它默认是换行的,末尾会多出一个空行来。
[解析]
第一行把内容拷贝到hold space,原因是 H 追加的话首行会是空行,然后匹配到 [ 标签符号就不会执行花括号里的操作,如果没匹配到呢就把该行 H 追加到 hold space 中,最后一行不 b ,因为跳了就没有下一个 [ 标签符号来激活了。然后 x 把两个空间的内容交换,看是否匹配到我们所要的关键字,如果匹配到就打印。
[解析]
这是 :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
[解析]
先对 [ 转义,然后设定为RS分隔符,当RT匹配到需要的字样的时候,把RT给一个变量保存,然后getline读取下一行(其实就是下个段落的内容)给变量i,最后打印匹配的段落分割符和下一行的内容,这个语句的关键地方是把RT在读取下一行之前就把它保存给一个变量,否则读取下一行时,RT就会跟随下一行的RS发生变化。
[解析]
这个例子和上个梢有不同,它是匹配标签,而上个例子是匹配标签段落里内容,因为第一行就是 [ 开头的,所以 x 交换的语句要排除第一行,就这一点区别。
[解析]
这儿呢 :a;N;ba 的组合没那么好使,因为它老要去把下一行的 [标签] 读出来,无奈只好替换了。
[解析]
这才是王道,我们不用 N 了,用 n 。首先把匹配到关键字标签的行打印,然后 n 移到下一行,看是否匹配标签的符号,如果没匹配就跳转,又打印该行,再 n 读取下一行,如果是最后一行,照样跳转去标签处,p 打印出内容,再 n 的时候,注意这是 GNU sed 的特点,当没有下一样读取和操作时,会中止整个命令,后面的命令不再运行,这样就避免了后面的 ba 死循环。N 同样有这个特性。