- 論壇徽章:
- 23
|
感謝斑竹加精。
關(guān)于sed記數(shù),補充2個例子,均來自info sed中的examples(略有改動)
例8:實現(xiàn) awk '{print NR,$0}' 的功能- ly5066113@ubuntu:~$ head sed.info | awk '{print NR,$0}'
- 1 File: sed.info, Node: Top, Next: Introduction, Up: (dir)
- 2
- 3 sed, a stream editor
- 4 ********************
- 5
- 6 This file documents version 4.1.5 of GNU `sed', a stream editor.
- 7
- 8 Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004 Free Software
- 9 Foundation, Inc.
- 10
- ly5066113@ubuntu:~$ head sed.info | sed -nf test.sed
- 1 File: sed.info, Node: Top, Next: Introduction, Up: (dir)
- 2
- 3 sed, a stream editor
- 4 ********************
- 5
- 6 This file documents version 4.1.5 of GNU `sed', a stream editor.
- 7
- 8 Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004 Free Software
- 9 Foundation, Inc.
- 10
- ly5066113@ubuntu:~$ cat test.sed
- #! /usr/bin/sed -f
- x
- 1s/^/1/
- G
- s/\n/ /p
- s/ .*//
- /^9*$/s/^/0/
- s/.9*$/x&/
- h
- s/.*x//
- y/0123456789/1234567890/
- x
- s/x.*//
- G
- s/\n//
- h
復(fù)制代碼 x #交換pattern space與hold space,保存讀入的內(nèi)容
1s/^/1/ #如果是第一行,初始化行號1
G #將保存的內(nèi)容追加回pattern space
s/\n/ /p #將換行替換為空格,并打印
s/ .*// #去處空格以后的所有內(nèi)容,pattern space只剩下行號
/^9*$/s/^/0/ #如果行號都為9,在前面補0
s/.9*$/x&/ #用x分隔不需要改變和需要改變的數(shù)字
h #將pattern space中的內(nèi)容保存到hold space
s/.*x// #刪除不需要改變的數(shù)字
y/0123456789/1234567890/ #對數(shù)字進行 +1 的操作
x #交換pattern space與hold space
s/x.*// #刪除需要改變的數(shù)字
G #將改變后的數(shù)字追加回pattern space
s/\n// #刪除換行,得到新的行號
h #保存新行號到hold space
整體的思路:
每讀入一行記錄,將保存在hold space中的行號(如果是第一行,需要初始化),和本行記錄合并輸出
然后將行號 +1 ,保存至hold space
代碼的核心部分就是實現(xiàn)“行號 +1”,具體做法:
將行號分為2個部分,一部分保持不變(此部分可能沒有),一部分進行改變,然后將需要改變的部分進行處理
將處理后的結(jié)果與前面不變的部分拼接在一起,形成新的行號,但這里有個情況需要考慮,就是進位
我們已實際的例子來看看
如果行號是 123
那么首先將其分成2個部分變?yōu)?nbsp; 12x3
x左邊的12不需要改變,x右邊的3需要變成4
那么就對3進行y/0123456789/1234567890/的操作,將其變成4
然后拼上前面的12變?yōu)?124
如果行號是129(需要進位)
那么首先將其分成2個部分變?yōu)?nbsp; 1x29
x左邊的1不需要改變,x右邊的29需要變成30
那么就對29進行y/0123456789/1234567890/的操作,將其變成30
然后拼上前面的1變?yōu)?130
這里面有個特殊情況需要考慮,就是如果行號都為9
9, 99, 999 之類的情況,那么我們需要在前面加數(shù)字0用做進位用
例9:實現(xiàn) wc -c 的功能- ly5066113@ubuntu:~$ wc -c urfile
- 254 urfile
- ly5066113@ubuntu:~$ sed -nf test.sed urfile
- 254
- ly5066113@ubuntu:~$ cat test.sed
- #! /usr/bin/sed -f
- s/./a/g
- H
- x
- s/\n/a/
- : a; s/aaaaaaaaaa/b/g; t b; b done
- : b; s/bbbbbbbbbb/c/g; t c; b done
- : c; s/cccccccccc/d/g; t d; b done
- : d; s/dddddddddd/e/g; t e; b done
- : e; s/eeeeeeeeee/f/g; t f; b done
- : f; s/ffffffffff/g/g; t g; b done
- : g; s/gggggggggg/h/g; t h; b done
- : h; s/hhhhhhhhhh//g
- : done
- $! {
- h
- b
- }
- : loop
- /a/! s/[b-h]*/&0/
- s/aaaaaaaaa/9/
- s/aaaaaaaa/8/
- s/aaaaaaa/7/
- s/aaaaaa/6/
- s/aaaaa/5/
- s/aaaa/4/
- s/aaa/3/
- s/aa/2/
- s/a/1/
- y/bcdefgh/abcdefg/
- /[a-h]/ b loop
- p
復(fù)制代碼 此段代碼雖然看起來煩瑣,但思路卻比上一例好理解。
每讀一行數(shù)據(jù),將里面所有的字符都替換成字母a,因為sed讀數(shù)據(jù)時會將換行符(\n)去掉
所以我們利用H命令產(chǎn)生的\n將其補充回來,也替換成字母a,統(tǒng)一做字符統(tǒng)計
為了節(jié)省內(nèi)存開銷,提高效率,這里做了進位的處理,就是將10個a替換成1個b,10個b替換成1個c 。。。
這樣到最后,字母a的個數(shù)就代表個位數(shù)字,字母b的個數(shù)就代表十位數(shù)字,字母c的個數(shù)代表百位數(shù)字。。。
如果最后剩下是這樣一串字符:
ccbbbbbaaaa
那么就表示總共的字符數(shù)為:254
本段代碼的統(tǒng)計是有上限的,如果字符數(shù)量超過1億,將無法得到正確結(jié)果
可以通過增加替換的次數(shù)來增加統(tǒng)計上限,如 s/hhhhhhhhhh/i/g , s/iiiiiiiiii/j/g 。。。 |
|