- 论坛徽章:
- 0
|
今天看到论坛中有人问: awk如何计算命令行的输入?
仔细想了想用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;
- }
复制代码 |
|