Chinaunix首页 | 论坛 | 博客
  • 博客访问: 92372601
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-18 23:30:50

作者:dbcat   
今天看到论坛中有人问:
仔细想了想用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;
}
阅读(577) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~