【知识涌升】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,进阶就这样,不做井底之蛙,人丑就要多读书

posted @ 2012-10-05 14:25  poiu_elab  阅读(373)  评论(0编辑  收藏  举报