ksb@mentor.cc.purdue.edu (Kevin Braunsdorf) (01/26/91)
Below please find a sed script that evals (a subset of bc): expr ::= expr '+' expr | expr '*' expr | '(' expr ')' | digits+ ; For example: echo "2*(1+(3+4)*(5+3))+14" | sed -f parens.sed outputs 128 Don't ask me to explain why -- it's a hack! N.B.: 1\ you might have to remove the #comments, and blank lines under some old seds. 2\ if you remove the paren pats we don't have to use the hold space, then this becomes (more) useful in long scripts 3\ it breaks HP-UX sed, GNU sed-1.06, and some others :-(. -- "Cold waves wash over, and drift away with dreams of youth So (our) time is stolen, I cannot hold you long enough..." -- Enya kayessbee, Kevin Braunsdorf, ksb@cc.purdue.edu, pur-ee!ksb, purdue!ksb # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # parens.sed # This archive created: Fri Jan 25 13:07:42 1991 # By: Kevin Braunsdorf (PUCC UNIX Group) sed 's/^H//' << \SHAR_EOF > parens.sed H H# this adds and multiplies with sed (ksb@cc.purdue.edu) H# ++ for a limited time only do (expr) too!!! H# Kevin S Braunsdorf, PUCC UNIX Group, purdue!ksb H# $Compile: echo "4+7*3" | sed -f %f H H# make sure the expression is well formed Hs/[ ]//g H/[+*\/-]$/{ H a\ H poorly formed expression, operator on the end H q H} H/^[+*\/]/{ H a\ H poorly formed expression, leading operator H q H} H H# fill hold space with done token Hx Hs/^.*/done/ Hx H H# main loop, process operators (*, + and () ) H: loop H/^\+/{ H s/// H b loop H} H/^\(.*\)(\([^)]*\))\(.*\)$/{ H H H s//\2/ H x H s/^\(.*\)\n\(.*\)(\([^()]*\))\(.*\)$/()\2@\4@\1/ H x H b loop H} H/^[0-9]*\*/b mul H/^\([0-9]*\)\+\([0-9+*]*\*[0-9]*\)$/{ H s//\2+\1/ H b loop H} H/^[0-9]*\+/{ H s/$/=/ H b add H} Hx H/^done$/{ H x H p H d H} H/^()/{ H s/// H x H G H s/\(.*\)\n\([^@]*\)@\([^@]*\)@\(.*\)/\2\1\3/ H x H s/[^@]*@[^@]*@\(.*\)/\1/ H x H b loop H} Hi\ Hhelp, stack problem Hp Hx Hp Hq H H# turn mul into add until 1*x -> x H: mul H/^0*1\*/{ H s/// H b loop H} H/^\([0-9]*\)0\*/{ H s/^\([0-9]*\)0\*\([0-9]*\)/\1*\20/ H b mul H} Hs/^\([0-9]*\)1\*/\10*/ Hs/^\([0-9]*\)2\*/\11*/ Hs/^\([0-9]*\)3\*/\12*/ Hs/^\([0-9]*\)4\*/\13*/ Hs/^\([0-9]*\)5\*/\14*/ Hs/^\([0-9]*\)6\*/\15*/ Hs/^\([0-9]*\)7\*/\16*/ Hs/^\([0-9]*\)8\*/\17*/ Hs/^\([0-9]*\)9\*/\18*/ Hs/\*\([0-9*]*\)/*\1+\1/ Hb mul H H# get rid of a plus term until 0+x -> x H: add H/^\+\([0-9+*]*\)=/{ H s//\1/ H b loop H} H/^\([0-9*]*\)\+=/{ H s//\1/ H b loop H} H/^\([0-9]*\)\+\([0-9*+]*\)\+=/{ H s//\2+\1/ H b loop H} H/^\([0-9]*\)0\+\([0-9]*\)\([0-9]\)=/{ H s//\1+\2=\3/ H b add H} H/^\([0-9]*\)\([0-9]\)\+\([0-9]*\)0=/{ H s//\1+\3=\2/ H b add H} H/^\([0-9]*\)0\+\([0-9*+]*\)\+\([0-9]*\)\([0-9]\)=/{ H s//\1+\2+\3=\4/ H b add H} H/^\([0-9]*\)\([0-9]\)\+\([0-9*+]*\)\+\([0-9]*\)0=/{ H s//\1+\3+\4=\2/ H b add H} Hs/^\([0-9]*\)1\+/\10+/ Hs/^\([0-9]*\)2\+/\11+/ Hs/^\([0-9]*\)3\+/\12+/ Hs/^\([0-9]*\)4\+/\13+/ Hs/^\([0-9]*\)5\+/\14+/ Hs/^\([0-9]*\)6\+/\15+/ Hs/^\([0-9]*\)7\+/\16+/ Hs/^\([0-9]*\)8\+/\17+/ Hs/^\([0-9]*\)9\+/\18+/ H Hs/9=\([0-9]*\)$/_=\1/ Hs/8=\([0-9]*\)$/9=\1/ Hs/7=\([0-9]*\)$/8=\1/ Hs/6=\([0-9]*\)$/7=\1/ Hs/5=\([0-9]*\)$/6=\1/ Hs/4=\([0-9]*\)$/5=\1/ Hs/3=\([0-9]*\)$/4=\1/ Hs/2=\([0-9]*\)$/3=\1/ Hs/1=\([0-9]*\)$/2=\1/ H/_/{ H s//_0/ H : inc H s/9_/_0/ H s/8_/9/ H s/7_/8/ H s/6_/7/ H s/5_/6/ H s/4_/5/ H s/3_/4/ H s/2_/3/ H s/1_/2/ H s/0_/1/ H s/\+_/+1/ H /_/b inc H} Hb add SHAR_EOF # End of shell archive exit 0