【知识涌升】sed进阶篇
看了daniel robbins的sed教程3讲,又进步了,继续来个进阶篇。
1. 首先,sed里面的&不光可以用来在行尾追加,还可以用在匹配的pattern尾部追加也可以追加在pattern的首部
s/one/111&/ #匹配首追加 s/one/&111/ #匹配尾追加
2. match variable在sed里面的用法是
s/P\(.*\)/\1/
3. =可以用来显示行号,但是是单起一行的
4. {}可以用来对一个地址进行多项的操作
1,5{ s/one/1 s/two/2 }
5. i\在行前面追加行,c\替换行,a\在行后面追加行
1,5i\ this is insert 6,10c\ this is substitute 11,15a\ this is append
6. N用来在处理的时候将下一行的内容读入(在后面有例子)
7. b用来跳转(后面有例子)
8. 当要对文件进行好几轮的处理时候,可以
sed -e '***' -e '***' -e '***' filename
几个有意思的小例子
1. unix2dos & dos2unix
#! /bin/sed -f
# unix2dos.sed s/[^\r]$/&\r/
#! /bin/sed -f # dos2unix.sed s/\r$//
说两句,这里面的意思是unix2dos,先检查行末一个字符不是\r,再进行替换,以防发生已经是dos的格式的文本再在后面多加了一个^M,而dos2unix就是最后一个字符如果是\r,那么就去掉。通过这里的例子我有了一点感悟就是说,其实每行进入到sed里面的东西其实都是没有\n的,如果是unix格式的话就只有到最后的一个字符,如果是windows格式的话就到最后的一个\r,\n其实是没有进入到编辑行内的,所以可以试验一下查找到\n,那么就输出一行XXX,你会发现没有匹配到,原因也就是进入sed的行是没有\n的,除非用N命令将下一行读入才能看到\n,就是这样~
2. tac(行颠倒)
#! /bin/sed -nf 1!G;$!h;$p
这个稍微解释一下,牵扯到两个buffer的概念,sed的一个buffer是匹配到的或者是地址制定到的buffer,叫pattern buffer或者叫做current buffer,另外一个是内部的存储区域叫hold buffer,有两个命令可以互相在两个buffer间传东西
h/H --> copy/append pattern space to hold space
g/G --> copy/append hold space to pattern space
那么这个脚本执行的时候首先就是在非第一行的时候将hold space里的东西append到pattern space里,再copy pattern space里的东西到hold space里面,接着在最后一行的时候打印(之前都是silent模式不打印)。脚本执行顺序是第一行进入pattern space,之后copy pattern space 到hold space里;接着第二行进入pattern space,之后将hold space 里的第一行append到pattern space里,这里两行相当于就已经颠倒行了,再将pattern space里面颠倒行copy 到 hold space里,以此类推,在最后一行进入到pattern space里的时候,将hold space再append到最后一行的后面,ok,处理完成,之后再打印现在在pattern space里面的东西就ok了。
3. QIF trans
想要将形式如
1 !Type:Bank 2 D08/28/2000 3 T-8.15 4 N 5 PCHECKCARD SUPERMARKET 6 ^ 7 D08/28/2000 8 T-8.25 9 N 10 PCHECKCARD PUNJAB RESTAURANT 11 ^ 12 D08/28/2000 13 T-17.17 14 N 15 PCHECKCARD SUPERMARKET
的文件转化成形式如
1 28 Aug 2000 food - - Y Supermarket 30.94 2 25 Aug 2000 watr - 103 Y Check 103 52.86
的文件,用sed处理的脚本如下
#! /bin/sed -f 1d /^^/d s/[[:cntrl:]]//g
首先是预处理,把第一行bank啥的给删掉,之后再把每个分隔符^给删掉行,再将控制字符都删掉(这里不是很清楚都包括神马,反正dos2unix是肯定可以的不知道什么^A, ^B神马的是不是),接下来是格式的处理了
1 /^D/ { 2 s/^D\(.*\)/\1\tOUTY\tINNY\t/ 3 s/^01/Jan/ 4 s/^02/Feb/ 5 s/^03/Mar/ 6 s/^04/Apr/ 7 s/^05/May/ 8 s/^06/Jun/ 9 s/^07/Jul/ 10 s/^08/Aug/ 11 s/^09/Sep/ 12 s/^10/Oct/ 13 s/^11/Nov/ 14 s/^12/Dec/ 15 s=^\(.*\)/\(.*\)/\(.*\)=\2 \1 \3= 16 N 17 N 18 N 19 s=\nT\(.*\)\nN\(.*\)\nP\(.*\)=NUM\2NUM\t\tY\t\t\3\tAMT\1AMT= 20 s/NUMNUM/-/ 21 s/NUM\([0-9]*\)NUM/\1/ 22 s/\([0-9]\),/\1/ 23 /AMT-[0-9]*.[0-9]*AMT/b fixnegs 24 s/AMT\(.*\)AMT/\1/ 25 s/OUTY/-/ 26 s/INNY/inco/ 27 b done 28 :fixnegs 29 s/AMT-\(.*\)AMT/\1/ 30 s/OUTY/misc/ 31 s/INNY/-/ 32 :done 33 }
这里面一些格式的处理技巧,比如首先先把一些要处理的东西变成中间形式,就像什么占位置的OUTY和INNY,不说,说说N这个指令,就是在处理pattern space的时候将下面的一行读进来,此时pattern space相当于就有了4行的内容
28 Aug 2000 OUTY INNY \nT-8.15\nN\nPCHECKCARD SUPERMARKET
此时再替换就方便了,像什么将\n去掉就能join之类的就不说了,接着23行的b就是branch,跳转指令,如果发现前面的pattern有匹配,那么就跳转,跳转到了fixnegs标签处,如果没有的话就正常执行完,ok,key都说了,这个例子也还不错,原文就是sed的daniel robbins的入门文章,地址
http://www.ibm.com/developerworks/linux/library/l-sed1/index.html http://www.ibm.com/developerworks/linux/library/l-sed2/index.html http://www.ibm.com/developerworks/linux/library/l-sed3/index.html
ok,进阶就这样,不做井底之蛙,人丑就要多读书