打印斐波那契序列的sed脚本

将这个脚本放在这里基于两个目的:

  • 这个脚本中用了许多的循环结构可作为上一篇的补充。
  • 同时这一篇用了模拟的数字运算——了解这种运算方法有助于以后学习一些经典的sed脚本或写出自已的算术脚本

by hq00e

# 打印斐波那契序列
# 文件名:fib.sed
# 调用:seq 10 | sed -f fib.sed  # 打印前10个数字
#       yes | sed -f fib.sed     # 打印序列直到溢出
 
# 这个脚本用模拟的方式进行数字运算。有关这种方法的更
# 多细节可以参考Greg Ubben写的教程:
# http://sed.sourceforge.net/grabbag/tutorials/
 
1{
# 下面字母串的长度决定了可打印的序列长度
# 可以修改下面的字串使之支持更多的序列
# s/.*/zyxwvutsrqponmlkjihgfedcba/
  s/.*/kjihgfedcba/
# 初始化序列为“1, 1”
  s/.*/ &a &a /; h; d
}
 
# 从hs取最后两组数字串进行运算
g
s/.* \(.*\) \(.*\) $/\1\2/
 
# 进行进位操作前先对两组数字加总(其实是排序)
s/\(\(.\)\2*\)/\1 /g
:lpsort
s/\(\([^ ]\)\2\{0,\}\)\( .*\)\2/\1\2\3/
tlpsort
s/ //g

# 调整加总的结果
# 加总时我们进行如下运算:
# edcbaa + edcbaaa = edcbaaaa
#    1   +    2    =     3
# 但实际在加总(排序)后我们等到的结果是:
# edcbaa + edcbaaa = eeddccbbaaaaa
# 我们需要将eeddccbbaaaaa转换为edcbaaaa
 
s/\(.\)\(\1\{1,19\}\)/\2/g
 
# 进行进位操作。
# baaaaaaaaaaa进位后成为bba——10
 
:doCarry
s/\(.\)\(\(.\)\3\{9\}\)\3/\1\1\3/
t doCarry
 
# 简单(粗糙)的溢出检验
# 因为第一个字母如果超过9个说明没有正常进位——即溢出
/^\(.\)\1\{9\}/{g;s/$/ ++OVERFLOW++/; b2digi}
 
# 将这一轮的结果保存到hold space。记得在最后加上一个空格。
G
s/\(.*\)\n\(.*\)/\2\1 /
$!{h;d}
g
 
# 运算完后将模拟结果转为数字表示的结果
:2digi
s/\([a-z]\)\1\{9\}/9/g
s/\([a-z]\)\1\{8\}/8/g
s/\([a-z]\)\1\{7\}/7/g
s/\([a-z]\)\1\{6\}/6/g
s/\([a-z]\)\1\{5\}/5/g
s/\([a-z]\)\1\{4\}/4/g
s/\([a-z]\)\1\{3\}/3/g
s/\([a-z]\)\1\1/2/g
s/\([a-z]\)\1/1/g
s/\([a-z]\)/0/g
s/ 0*/ /g
# 溢出检验需要q命令
q

[--结束--]


About this entry