今天看到论坛中有人问:
仔细想了想用awk确实不好做。因为awk中没有像其它语言
中的eval函数,于是自己试着编了一个eval函数,用来进
行表达式求值。
用stack对运算符号及数值进行处理是这个脚本的关键。
由于时间有限,我只实现了+-*/%五种运算。代码写的比较
粗糙,欢迎大家批评指正。
用法(表达式必须以"@"结束):
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' )
代码:
#! /usr/bin/awk
# simple expression evaluator awk version
# author : dbcat at chinaunix.net
# 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 "@"
# 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;
}