Arithmetik mit sed

Wie man mit dem Streameditor sed auch rechnen kann, zeigen folgende Programme die zwei ganze Zahlen addieren bzw. multiplizieren können. Gegenüber normaler Computerarithmetik haben die Programme den Vorteil, dass sie mit beliebiger Genauigkeit rechnen können. Die Zwischenschritte werden dabei mittels des Befehls p ausgegeben.

Das Additionsprogramm:
#!/bin/sh
# Dieses Script addiert zwei Zahlen. Die Eingabe muss in der Form <Zahl1>+<Zahl2> 
# erfolgen.
#
sed -re '
# add a = at the end of the input
s/$/=/
# kill all whitespaces
s/\s//g
# remove one digit if right op ends on zero or
# decrement right op and set carry mark ` on left op
# and branch to carry 
: add {
p
s/([0-9]*)([0-9])\+([0-9]*)0=([0-9]*)/\1\+\3=\2\4/;t add
s/([0-9]+)\+([0-9]*)1=([0-9]*)/\1`\+\20=\3/;t carry
s/([0-9]+)\+([0-9]*)2=([0-9]*)/\1`\+\21=\3/;t carry
s/([0-9]+)\+([0-9]*)3=([0-9]*)/\1`\+\22=\3/;t carry
s/([0-9]+)\+([0-9]*)4=([0-9]*)/\1`\+\23=\3/;t carry
s/([0-9]+)\+([0-9]*)5=([0-9]*)/\1`\+\24=\3/;t carry
s/([0-9]+)\+([0-9]*)6=([0-9]*)/\1`\+\25=\3/;t carry
s/([0-9]+)\+([0-9]*)7=([0-9]*)/\1`\+\26=\3/;t carry
s/([0-9]+)\+([0-9]*)8=([0-9]*)/\1`\+\27=\3/;t carry
s/([0-9]+)\+([0-9]*)9=([0-9]*)/\1`\+\28=\3/;t carry
s/^([0-9]*)\+=(.*)/\1\2/;t
s/^\+([0-9]*)=(.*)/\1\2/;t
T
}
# increment digit and do carry handling to next digit
: carry {
p
s/^`(.*)/1\1/;t add
s/(.*)0`(.*)/\11\2/;t add
s/(.*)1`(.*)/\12\2/;t add
s/(.*)2`(.*)/\13\2/;t add
s/(.*)3`(.*)/\14\2/;t add
s/(.*)4`(.*)/\15\2/;t add
s/(.*)5`(.*)/\16\2/;t add
s/(.*)6`(.*)/\17\2/;t add
s/(.*)7`(.*)/\18\2/;t add
s/(.*)8`(.*)/\19\2/;t add
s/(.*)9`(.*)/\1`0\2/;t carry
}
'
und das Programm zu Multiplikation.
#!/bin/sh

sed -re '
# kill all whitespaces
s/\s//g
# add a = at the end of the input
s/$/= r0: r1:/
s/\*/x/
s/([0-9]*)([0-9])x([0-9]*)([0-9])=/\1\2<x\3\4<=/
#
: mult {
p
s/r0:(.*) r1:(0*)/r0:\1\+\2= r1:\2/
s/([0-9])(<.*)([0-9])(<.* r0:.*\+)/\1\2\3\4\1x\3/;t dmult
T
}
: dmult {
p
s/\+0x[0-9]/\+0/;t add
s/\+1x([0-9])/\+\1/;t add
s/\+2x2/\+4/;t add
s/\+2x3/\+6/;t add
s/\+2x4/\+8/;t add
s/\+2x5/\+10/;t add
s/\+2x6/\+12/;t add
s/\+2x7/\+14/;t add
s/\+2x8/\+16/;t add
s/\+2x9/\+18/;t add
s/\+3x3/\+9/;t add
s/\+3x4/\+12/;t add
s/\+3x5/\+15/;t add
s/\+3x6/\+18/;t add
s/\+3x7/\+21/;t add
s/\+3x8/\+24/;t add
s/\+3x9/\+27/;t add
s/\+4x4/\+16/;t add
s/\+4x5/\+20/;t add
s/\+4x6/\+24/;t add
s/\+4x7/\+28/;t add
s/\+4x8/\+32/;t add
s/\+4x9/\+36/;t add
s/\+5x5/\+25/;t add
s/\+5x6/\+30/;t add
s/\+5x7/\+35/;t add
s/\+5x8/\+40/;t add
s/\+5x9/\+45/;t add
s/\+6x6/\+36/;t add
s/\+6x7/\+42/;t add
s/\+6x8/\+48/;t add
s/\+6x9/\+54/;t add
s/\+7x7/\+49/;t add
s/\+7x8/\+56/;t add
s/\+7x9/\+63/;t add
s/\+8x8/\+64/;t add
s/\+8x9/\+72/;t add
s/\+9x9/\+81/;t add
s/\+([0-9])x([0-9])/\+\2x\1/;t dmult

}
: add {
p
s/(.*r0:[0-9]*)([0-9])\+([0-9]*)0=([0-9]*)/\1\+\3=\2\4/;t add
s/(.*r0:[0-9]+)\+([0-9]*)1=([0-9]*)/\1`\+\20=\3/;t carry
s/(.*r0:[0-9]+)\+([0-9]*)2=([0-9]*)/\1`\+\21=\3/;t carry
s/(.*r0:[0-9]+)\+([0-9]*)3=([0-9]*)/\1`\+\22=\3/;t carry
s/(.*r0:[0-9]+)\+([0-9]*)4=([0-9]*)/\1`\+\23=\3/;t carry
s/(.*r0:[0-9]+)\+([0-9]*)5=([0-9]*)/\1`\+\24=\3/;t carry
s/(.*r0:[0-9]+)\+([0-9]*)6=([0-9]*)/\1`\+\25=\3/;t carry
s/(.*r0:[0-9]+)\+([0-9]*)7=([0-9]*)/\1`\+\26=\3/;t carry
s/(.*r0:[0-9]+)\+([0-9]*)8=([0-9]*)/\1`\+\27=\3/;t carry
s/(.*r0:[0-9]+)\+([0-9]*)9=([0-9]*)/\1`\+\28=\3/;t carry
s/(.*r0:)([0-9]*)\+=(.*)/\1\2\3/;t nmult
s/(.*r0:)\+([0-9]*)=(.*)/\1\2\3/;t nmult
T
}
# increment digit and do carry handling to next digit
: carry {
p
s/(r0:)`(.*)/\11\2/;t add
s/(.*)0`(.*)/\11\2/;t add
s/(.*)1`(.*)/\12\2/;t add
s/(.*)2`(.*)/\13\2/;t add
s/(.*)3`(.*)/\14\2/;t add
s/(.*)4`(.*)/\15\2/;t add
s/(.*)5`(.*)/\16\2/;t add
s/(.*)6`(.*)/\17\2/;t add
s/(.*)7`(.*)/\18\2/;t add
s/(.*)8`(.*)/\19\2/;t add
s/(.*)9`(.*)/\1`0\2/;t carry
}
: nmult {
p
s/(x[0-9]+)([0-9])<(.*r1:)/\1<\2\30/;t mult
s/([0-9]+)([0-9])<([0-9]*x)([0-9])<([0-9]*)=(.*r0:[0-9]*)([0-9])(.*r1:).*/\1<\2\3\4\5<=\7\6\8/;t mult
s/<//g
s/(.*)=([0-9]*)(.*r0:)([0-9]*).*/\1=\4\2/
}
'