Home > Archive > AWK > April 2006 > Simple expression evaluator by awk.
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Simple expression evaluator by awk.
|
|
| deeperbluecat@gmail.com 2006-04-13, 9:57 pm |
| I wrote this very simple script yesterday . It can evaluate simple
numeric expression ( eg :echo "(3-1)*2.3-8.5%3-(9.12+2*3)/2@" | awk -f
eval.awk ).
Now i want "sin cos log ...." operator is supported by this script
..Maybe write a binary tree structure is much better than a stack . But
i am not sure how to do this in awk .
Anyone can help or any comments to this script?
Thanks!
code:
========================================
========================================
=====
#! /usr/bin/awk
# simple expression evaluator awk version
# author : dbcat
# email: deeperbluecat@gmail.com
# usage: example :
# echo "(3-1)*2.3-8.5%3-(9.12+2*3)/2@" | awk -f eval
# echo 1+2+3*2 @| awk -f eval
# awk -f eval <( seq 1 100|tr "\n" "+"|sed 's/+/@/100' )
# expression must be end with "@"
# Under GNU bash, version 3.00.16(1)-release (i586-suse-linux)
# GNU Awk 3.1.4
# have fun
BEGIN{
symbol="+-*%/()@";
oppr["++"]=">";oppr["+-"]=">";oppr["+*"]="<";oppr["+/"]="<";oppr["+%"]="<";oppr["+("]="<";
oppr["+)"]=">";oppr["+@"]=">";
oppr["-+"]=">";oppr["--"]=">";oppr["-*"]="<";oppr["-/"]="<";oppr["-%"]="<";oppr["-("]="<";
oppr["-)"]=">";oppr["-@"]=">";
oppr["*+"]=">";oppr["*-"]=">";oppr["**"]=">";oppr["*/"]=">";oppr["*%"]="<";oppr["*("]="<";
oppr["*)"]=">";oppr["*@"]=">";
oppr["/+"]=">";oppr["/-"]=">";oppr["/*"]=">";oppr["//"]=">";oppr["/%"]="<";oppr["/("]="<";
oppr["/)"]=">";oppr["/@"]=">";
oppr["%+"]=">";oppr["%-"]=">";oppr["%*"]=">";oppr["%/"]=">";oppr["%%"]=">";oppr["%("]="<";
oppr["%)"]=">";oppr["%@"]=">";
oppr["(+"]="<";oppr["(-"]="<";oppr["(*"]="<";oppr["(/"]="<";oppr["(%"]="<";oppr["(("]="<";
oppr["()"]="=";
oppr[")+"]=">";oppr[")-"]=">";oppr[")*"]=">";oppr[")/"]=">";oppr[")%"]=">";
oppr["))"]=">";oppr[")@"]=">";
oppr["@+"]="<";oppr["@-"]="<";oppr["@*"]="<";oppr["@/"]="<";oppr["@("]="<";oppr["@%"]="<";
oppr["@@"]="=";
}
{
gsub(/[-*%+()/@]/," & ",$0);
expression=$0;
}
END{
split(expression,Ex," ");
print evaluate(Ex);
}
function evaluate(Ex,OP,OF,c,k,t,x,str,y,r)
{
k=1;
push(OP,"@");
c=Ex[k];
while(c!="@" || gettop(OP)!="@")
{
if(index(symbol,c)==0)
{
push(OF,c);
k=k+1;
c=Ex[k];
}else
{
t=priority(oppr,gettop(OP),c);
if(t=="<")
{
push(OP,c);
k=k+1;
c=Ex[k];
}else if(t=="=")
{
pop(OP);
k=k+1;
c=Ex[k];
}else{
str=pop(OP);
y=pop(OF);
x=pop(OF);
r=calculate(x,str,y);
push(OF,calculate(x,str,y));
}
}
}
return gettop(OF);
}
function calculate(x,st,y)
{
if(st=="+")
return x+y;
else if(st=="-")
return x-y;
else if(st=="*")
return x*y;
else if(st=="%")
return x%y;
else if(st=="/")
return x/y;
}
function priority(oppr,op1,op2)
{
return oppr[op1""op2];
}
function gettop(arr,k,t)
{
k=0;
for(t in arr)
{
k++;
}
return arr[k-1];
}
function push(arr,x,t,k)
{
k=0;
for(t in arr)
{
k++;
}
arr[k]=x;
}
function pop(arr,va,t,u)
{
u=0;
for(t in arr)
{
u++;
}
va=arr[u-1];
delete arr[u-1];
return va;
}
========================================
========================================
========
| |
| Jürgen Kahrs 2006-04-14, 3:56 am |
| deeperbluecat@gmail.com wrote:
> Now i want "sin cos log ...." operator is supported by this script
> .Maybe write a binary tree structure is much better than a stack . But
> i am not sure how to do this in awk .
> Anyone can help or any comments to this script?
Use Google and search for "Alan Linton calc3".
This problem has been solved many times. For
example in chapter 6.5 of TAPL:
http://cm.bell-labs.com/cm/cs/awkbook/index.html
| |
|
| Thank you for your reply.I find that article and read it. it's really
help me
a lot. But i dont really understand the things they talked
about.Because i dont speak english,i live in china.
My friends give me a suggestion about this topic . See this situation:
echo "1+2+3"| xargs -i awk 'BEGIN{print {}}'
we can pass the result using xargs. We also can pass the expression
using "getline" function within awk right?
so see this:
===========================
$ echo "1+2*(2+1.1)
> sin(1)+exp(2)
> 3%5-cos(1.2-3.4)" |awk '{a=$0;cmd="awk \047BEGIN{print "$0" }\047";cmd|getline ;close(cmd);print a"="$0}'
1+2*(2+1.1)=7.2
sin(1)+exp(2)=8.23053
3%5-cos(1.2-3.4)=3.5885
==========================
May be a little tricky. Using awk itself to get the result . Can i call
it eval?
Thanks !
| |
| Jürgen Kahrs 2006-04-14, 7:56 am |
| dbcat wrote:
> My friends give me a suggestion about this topic . See this situation:
> echo "1+2+3"| xargs -i awk 'BEGIN{print {}}'
> we can pass the result using xargs. We also can pass the expression
> using "getline" function within awk right?
Yes, you can use both.
> so see this:
> ===========================
> $ echo "1+2*(2+1.1)
>
> 1+2*(2+1.1)=7.2
> sin(1)+exp(2)=8.23053
> 3%5-cos(1.2-3.4)=3.5885
> ==========================
> May be a little tricky. Using awk itself to get the result .
Yes it is tricky. I think this problem can be
solved without all the tricks.
> Can i call it eval?
The name eval is a bit unfortunate because users expect
eval to be able to execute uder-defined functions. We
have had discussions here about eval in the past.
| |
|
|
| John DuBois 2006-04-14, 6:57 pm |
| In article <4a99c5Fs59vaU1@individual.net>,
Jürgen Kahrs <Juergen.KahrsDELETEHIS@vr-web.de> wrote:
>deeperbluecat@gmail.com wrote:
>
>
>Use Google and search for "Alan Linton calc3".
The last version of that that I saw had problems...
$ gawk -f ./calc3 --source='BEGIN{print eval("1*1*1")}'
An error occurred at *1
I started to fix it, but ended up deciding that a somewhat different approach
was needed, and wrote this:
ftp://ftp.armory.com/pub/lib/awk/eval
It probably has problems too, but I haven't found them yet :)
John
--
John DuBois spcecdt@armory.com KC6QKZ/AE http://www.armory.com/~spcecdt/
| |
|
| hello, i write this simple and funny version:
=======================
#! /usr/bin/awk
# by dbcat
# GNU Awk 3.1.4
BEGIN{
# TEST
eval("2.1+sin(1.1-log(23))")
eval("1*1*1")
eval(pp(1)+1)
}
function eval(cmd,expression)
{
expression = "awk \047BEGIN{print "cmd" }\047"
system(expression)
}
function pp(x)
{
return cos(sin(x))
}
=======================
I am not sure whether it works under windows or other awk version.^_^
Regards
|
|
|
|
|