sed can do math, cool!

Kevin Braunsdorf ksb at mentor.cc.purdue.edu
Sat Jan 26 05:26:26 AEST 1991


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 at 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 at 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



More information about the Comp.unix.shell mailing list