- 論壇徽章:
- 0
|
今天看到論壇中有人問(wèn): awk如何計(jì)算命令行的輸入?
仔細(xì)想了想用awk確實(shí)不好做。因?yàn)閍wk中沒(méi)有像其它語(yǔ)言
中的eval函數(shù),于是自己試著編了一個(gè)eval函數(shù),用來(lái)進(jìn)
行表達(dá)式求值。
用stack對(duì)運(yùn)算符號(hào)及數(shù)值進(jìn)行處理是這個(gè)腳本的關(guān)鍵。
由于時(shí)間有限,我只實(shí)現(xiàn)了+-*/%五種運(yùn)算。代碼寫的比較
粗糙,歡迎大家批評(píng)指正。
用法(表達(dá)式必須以"@"結(jié)束):
- 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' )
復(fù)制代碼
代碼:
- #! /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{
- # 運(yùn)算符集合
- symbol="+-*%/()@";
- # 構(gòu)造運(yùn)算符優(yōu)先級(jí)關(guān)系
- 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{
- # 分解表達(dá)式
- split(expression,Ex," ");
-
- print evaluate(Ex);
- }
- # 表達(dá)式求值函數(shù)
- 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);
- }
- # 二元運(yùn)算函數(shù)
- 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;
- }
- # 優(yōu)先級(jí)別比較
- 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];
- }
- # 進(jìn)棧函數(shù)
- function push(arr,x,t,k)
- {
- k=0;
- for(t in arr)
- {
- k++;
- }
- arr[k]=x;
- }
- # 出棧函數(shù)
- function pop(arr,va,t,u)
- {
- u=0;
- for(t in arr)
- {
- u++;
- }
- va=arr[u-1];
- delete arr[u-1];
- return va;
- }
復(fù)制代碼 |
|