高级 Sed 秀
时间:2006-01-12 来源:dbcat
问题:
怎样用SED来实现PASTE功能?
如 PASTE FILE1 FILE2 ?
嘻嘻,是不是很难?
不急,乖 ,一起看看怎么来完成这个MISSION IMPOSSIBLE .
首先,为了方便起见,我们把文件的每一行抽象做一个字符.
那么
SED 'COMMANDS' F1 F2
1 A
2 B
3 C
可以转化为,如何做到:
SED 'COMMANDS' F1 F2
1
A
2
B
3
C
又可以变为:
SED 'COMMANDS' F1 F2
1 2 3
A B C
而 1 2 3可以用 命令替换做到:
SED 'COMMANDS' <(SED 'COMMANDS' F1) <(SED 'COMMANDS' F2)
那么,如何用SED将:
1 2 3 4 5 6 7 8 9
A B C D E F G H I
变化为:
1 A
2 B
3 C
4 D
5 E
6 F
7 G
8 H
9 I
只要它解决了,PASTE的问题就OK了.但这是一道非常有难度的文本转换题目. 如果用AWK或SHELL来完成的话并不复杂,但是用SED来做的话就很有难度了.
让我们看看SED高手们是怎么做的:
SHELL解法:
寂寞烈火
怎样用SED来实现PASTE功能?
如 PASTE FILE1 FILE2 ?
嘻嘻,是不是很难?
不急,乖 ,一起看看怎么来完成这个MISSION IMPOSSIBLE .
首先,为了方便起见,我们把文件的每一行抽象做一个字符.
那么
SED 'COMMANDS' F1 F2
1 A
2 B
3 C
可以转化为,如何做到:
SED 'COMMANDS' F1 F2
1
A
2
B
3
C
又可以变为:
SED 'COMMANDS' F1 F2
1 2 3
A B C
而 1 2 3可以用 命令替换做到:
SED 'COMMANDS' <(SED 'COMMANDS' F1) <(SED 'COMMANDS' F2)
那么,如何用SED将:
1 2 3 4 5 6 7 8 9
A B C D E F G H I
变化为:
1 A
2 B
3 C
4 D
5 E
6 F
7 G
8 H
9 I
只要它解决了,PASTE的问题就OK了.但这是一道非常有难度的文本转换题目. 如果用AWK或SHELL来完成的话并不复杂,但是用SED来做的话就很有难度了.
让我们看看SED高手们是怎么做的:
SHELL解法:
寂寞烈火
CODE:
[Copy to clipboard]
/home/lee#cat _test
#!/bin/ksh
#假定固定文件是10个域
n=1
while read line;do
set -A array$n $line
((n++))
done<file
varlist=$(
for j in $(typeset);do
[[ $j == array[0-9] ]] && echo \${$j[\$m]}
done
)
m=0
while((m<=10));do
eval echo $varlist
((m++))
done
SED解法:
FAINTBLUE:
#!/bin/ksh
#假定固定文件是10个域
n=1
while read line;do
set -A array$n $line
((n++))
done<file
varlist=$(
for j in $(typeset);do
[[ $j == array[0-9] ]] && echo \${$j[\$m]}
done
)
m=0
while((m<=10));do
eval echo $varlist
((m++))
done
SED解法:
FAINTBLUE:
CODE:
[Copy to clipboard]
:a
H;ta
$ {
x
s/\n/ @/g
s/$/ /
s/ //
x
:b
g
s/ [^@]*$//
s/ [^@]*@/ /g
s/@//
p
g
s/@../@/g
h
/@@/!tb
} 瓦克尔(这个真是太酷了,还有说明):
H;ta
$ {
x
s/\n/ @/g
s/$/ /
s/ //
x
:b
g
s/ [^@]*$//
s/ [^@]*@/ /g
s/@//
p
g
s/@../@/g
h
/@@/!tb
} 瓦克尔(这个真是太酷了,还有说明):
CODE:
[Copy to clipboard]
H #保存所有行
${ #最后一行处理,与AWK的END相似
:a
g #取得保留空间内容
s/\n[^\n]/\n/g #把第一个不是换行符删除
:b #与下面一句形成循环
/[^\n]/s/\n\n/\n \n/g;tb #其实是补位用的
x #交换保留/模式空间内容,这时保留空间已经没有每"行"的第一个字符了
s/\n\+\([^\n]\)[^\n]*/\1/gp;ta #打印出模式空间的所有"行"的第一个字符,再去:a处处理保留空间的内容
}
007:
有了以上代码,我们就可以用SED来实现PASTE的功能了.
${ #最后一行处理,与AWK的END相似
:a
g #取得保留空间内容
s/\n[^\n]/\n/g #把第一个不是换行符删除
:b #与下面一句形成循环
/[^\n]/s/\n\n/\n \n/g;tb #其实是补位用的
x #交换保留/模式空间内容,这时保留空间已经没有每"行"的第一个字符了
s/\n\+\([^\n]\)[^\n]*/\1/gp;ta #打印出模式空间的所有"行"的第一个字符,再去:a处处理保留空间的内容
}
007:
CODE:
[Copy to clipboard]
sed -n 'H;${:a; g; s/\(\n\)[^\n]/\1/g; :b; /[^\n]/s/\(\n\)\1/\1 \1/g;tb; x; s/\n\+\([^\n]\)[^\n]*/\1/gp;ta}' |
有了以上代码,我们就可以用SED来实现PASTE的功能了.
CODE:
[Copy to clipboard]
$cat a 1 2 3 4 5 6 7 $cat b a b c d e f g h $ sed -n 'H;${:a; g; s/\(\n\)[^\n]/\1/g; :b; /[^\n]/s/\(\n\)\1/\1 \1/g;tb; x; s/\n\+\([^\n]\)[^\n]*/\1 /gp;ta}' <(sed ':t;N;$!bt;s/\n/ /g' a) <(sed ':t;N;$!bt;s/\n/ /g' b) 1 a 2 b 3 c 4 d 5 e 6 f 7 g h
|
|
|
相关阅读 更多 +