Tuesday, June 24, 2014

awk: functions

1. awk function basic
script_1:
 #! /bin/bash  
   
 awk 'BEGIN{  
 #Following example demostrates that if passing in  
 #string variables, awk will take the copy instead  
 #of the reference, that is why v1, v2 at BEGIN section  
 #does not get changed even if they are changed inside  
 #func1.   
   
   v1="Hello world!";  
   v2="Amazing world!";  
   
   res=func1(v1, v2);  
    
   print v1;  
   print v2;  
   print res;  
   #output:  
   #Hello world!  
   #Amazing world!  
   #100  
   
 #Following example demostrates that if passing in  
 #array variables, awk will take the reference instead  
 #of the copy. Code in func2 installs 2 entries in   
 #the array, and it is reflected from the caller side.  
 #By the way, func2 does not return any value, so by   
 #default, the return value is empty string. But this  
 #is implementation dependent feature, in some other  
 #platforms, it may return numeric 0.  
   va[0]="Hello";  
   va[1]="world!";  
   
   res=func2(va);  
   for(i in va)  
     print va[i];  
   #output:  
   #0  
   #1  
   #Hello  
   #world!  
   
   print res;  
   #output: empty line  
 }  
   
 function func1(v1, v2)  
 {  
   temp=v1;  
   v1=v2;  
   v2=temp;  
   
   return 100;  
 }  
   
 function func2(va)  
 {  
   va["Hello"]=0;  
   va["world"]=1;  
 }  
 '  

2. Management of Variables
A bad way:
script_1:
 #! /bin/bash  
   
 #Variables name clashing is a big source for awk bugs  
 #For function, if it is using a variable whose name is  
 #not listed in arguments, then it is taken as global   
 #variable. If it is listed in arguments, awk will hide  
 #any global variables with same name  
   
 #At following example, we expect p not getting changed.  
 #After calling find_key, we want to print out the original  
 #string saved in "p". But p is used inside find_key, and  
 #it is taken as global variable, and value get changed there  
 #Its value is the last key in array.  
 awk 'BEGIN {  
   p="Hello world!";  
   va[0]="Hello";  
   va[1]="World";  
   key=find_key(va, "World");  
   print p;  
   print key;  
   
   #Output:  
   #1  
   #1  
 }  
 function find_key(va, value)  
 {  
   for(p in va)  
   {  
     if(va[p] == value)  
       return p;  
   }  
   return "";  
 }'  
========================================
A good way:
script_1:
 #! /bin/bash  
   
 awk 'BEGIN {  
   p="Hello world!";  
   va[0]="Hello";  
   va[1]="world!";  
   key = find_key(va, "world!");  
    
   print p;  
   print key;  
   
   #Output:  
   #Hello world!  
   #1  
 }  
   
 # We declare the p explictly so local variable  
 # p will hide the global one. And their value  
 # will not be clashed any more.  
 function find_key(va, value, p)  
 {  
   for(p in va)  
   {  
     if(va[p] == value)  
       return p;  
   }  
   
   return "";  
 }'  

3. Recursive Function
Write a function to get the greatest common denominator
./script_1:
 #! /bin/bash  
   
 awk -v x=$1 -v y=$2 'BEGIN {  
   r=getMaxCd(x,y);  
   print "getMaxCd(",x,",",y,")=",r;  
 }  
   
 # We need to declare the "r" at the argument list to  
 # hide the global "r" variable  
 function getMaxCd(x, y,  r)  
 {  
   x=int(x);  
   y=int(y);  
   print x,"%",y;  
   r=x % y;  
   return (r==0)? y : getMaxCd(y, r);  
 }'  

terminal:
 aubinxia@aubinxia-fastdev:~$ ./script_1 10 4  
 10 % 4  
 4 % 2  
 getMaxCd( 10 , 4 )= 2  
 aubinxia@aubinxia-fastdev:~$ ./script_1 100 33  
 100 % 33  
 33 % 1  
 getMaxCd( 100 , 33 )= 1  

No comments:

Post a Comment