日历

2019年八月
« 5月    
 1234
567891011
12131415161718
19202122232425
262728293031  

最近评论

    AWK的使用

    awk使用 第十二部分 awk主题函数Actions的指令语法

        awk的Actions一般由下列指令(statement)所组成:    
    1、 表达式 ( function calls, assignments..)    
    2、print 表达式列表    
    3、printf( 格式化字符串, 表达式列表)    
    4、if( 表达式 ) 语句 [else 语句]   
    5、while( 表达式 ) 语句    
    6、do 语句 while( 表达式)   
    7、for( 表达式; 表达式; 表达式) 语句    
    8、for( variable in array) 语句    
    9、delete    
    10、break    
    11、continue    
    12、next    
    13、exit [表达式]    
    14、语句
        在awk 中大部分指令和C 语言中的用法一致,这里仅介绍比较常用或容易混淆的指令的用法。

    一、流程控制指令
         if 指令
        语法:if (表达式) 语句1 [else 语句2 ]
        范例:
       [root@myfreelinux pub]# cat inte
    123
    324
    [root@myfreelinux pub]# cat action.awk
    #!/bin/awk -f
    {
    if($0>100)
     print “the number is :” $0
    else
     print “the number add 100 is :” $0+100
    }
    [root@myfreelinux pub]# awk -f action.awk inte
        上例中if语句的用法和C 语言中相同,1、如果表达式计算(evaluate)的值小于100, 则执行 print “the number is :” $0;否则执行print “the number add 100 is :” $0+100
        2、进行逻辑判断的表达式所返回的值有两种,如果逻辑值为true,则返回1,否则返回0。
        3、语法中else 语句2以[ ] 前后括住表示该部分根据需要加入或省略。

        while 指令
        语法:while( 表达式 ) 语句
        范例:
        while( match(buffer,/[0-9]+\.c/ ) )
        { print “Find :” substr( buffer,RSTART,RLENGTH)
        buff = substr( buffer,RSTART + RLENGTH) }
        上例找出buffer中所有能匹配/[0-9]+.c/(数字之后接上  “.c”的所有子字符串)。while以函数match( )所返回的值做为判断条件。如果buffer中含有匹配指定条件的子字符串(match成功),则match()函数返回1,while 将持续进行其后的语句,while执行的条件是只要条件为真就会执行,知道判断条件为假停止执行判断语句。

        do-while 指令
        语法:
        do 语句 while(表达式)
        范例:
        do{ print “Enter y or n ! ” getline data }
        while( data !~ /^[YyNn]$/)    
       1、上例要求用户从键盘上输入一个字符,如果该字符不是Y,y,N或n,则会不停执行该循环,直到读取正确字符为YyNn为止。
        2、do-while 指令与while 指令最大的差异是:do-while指令会先执行一次语句,然后再判断是否应继续执行。 所以,无论条件是否成立,语句至少会执行一次。

        for循环语句
       
    语法一:for(variable in  array ) statement
        范例:执行一下awk语句:
    [root@myfreelinux pub]# awk ‘BEGIN{a[“one”]=1;a[2]=2;a[“three”]=3;for(one_array in a) printf(“a[%s]=%d\n”,one_array,a[one_array]);}’
    a[three]=3
    a[2]=2
    a[one]=1
        1、for循环可以查找数组中所有的下标值,并依次使用所指定的变量记录这些下标值,以本例而言,变量one_array将依次代表 “three”,“2”,“one”
        2、for循环指令查找出的下标值之间没有任何次续关系。

        语法二 :
        for(expression1; expression2; expression3) statement
        范例:for(i=1; i<=10; i++)  sum=sum + i
        说明:1、上例用来计算1加到10的总和。
        2、expression1常用于设定该for 循环的起始条件,如 i=1;expression2 用于设定该循环的停止条件,比如i<=10;expression3 常用于改变expression1的值,直到使表达式2满足条件跳出循环,如i++。

         break指令
        break指令用以强迫中断(跳离) for,while,do-while 等循环。
        范例:
        while(getline < “datafile” > 0 )
        { if( $1 == 0 )    break    
          else   print $2/$1 }
        上例中,awk 不断地从数据文件datafile中读取资料,当$1等于0时,停止该执行循环。

        continue 指令
        循环中的运行一部分是,执行continue指令来跳过循环中尚未执行的语句。
         范例:
        for( index in X_array)
         { if( index !~ /[0-9]+/ ) 
           continue    
            print “Juest  print the digital  index”, index }
        上例中如果index不是数字则执行continue,即跳过后面的print语句。continue和break 是不同的:continue只是跳过后面没有执行的语句,但不会离开该循环。

        next 指令
        执行next指令时,awk会跳过next指令之后的所有语句,包括next之后的所有Pattern { Actions },接着读取下一笔数据行,继续从第一个 Pattern {Actions} 执行起。
        范例:

    [root@myfreelinux pub]# cat integer
    222 111
    333 111

    444 111
    [root@myfreelinux pub]# cat action.awk
    #!/bin/awk -f
    {
    if(/^[ \t]*$/)
     {
     print “this is a blank line,nothing here!”;
     next;
     }
    $2!=0
     {
     printf(“$1 is %d,$2 is %d,$2/$1 is %d\n”,$1,$2,$1/$2);
     }
    }
    [root@myfreelinux pub]# awk -f action.awk integer
    $1 is 222,$2 is 111,$2/$1 is 2
    $1 is 333,$2 is 111,$2/$1 is 3
    this is a blank line,nothing here!
    $1 is 444,$2 is 111,$2/$1 is 4
       说明:awk 读入的数据行为空白行时( match /^[ \]*$/ ),除打印消息外只执行next,即awk将跳过其后的指令,继续读取下一行数据,从头开始并再次执行if(/^[ \t]*$/)语句

        exit 指令
        执行exit 指令时,awk将立刻跳离(停止执行)awk程序。

        awk 中的I/O指令
        printf 指令 
        printf指令与C 语言中的用法相同,使用这个指令可以控制数据输出时的格式。
        语法:printf(“format”, item1, item2,.. )
        范例: printf(“$1 is %d,$2 is %d,$2/$1 is %d\n”,$1,$2,$1/$2);
       1、format 部分是由一般的字串(String Constant) 和格式控制字符(Formatcontrol letter,其前会加上一个%字符)所构成。%s 和%d是最常用的格式控制字符.
        2、一般字串将被原封不动地打印出来,遇到格式控制字符时,依序把format后方的item转换成所指定的格式后进行打印。
       3、print和printf后民可使用> 或>>将输出到stdout 的数据重定向到其它文件,
        print 指令
        范例: print “Juest  print the digital  index”, index
        1、这个例子是上面打印数组下标的例子
        2、print 之后可接上字串常数(Constant String)或变量,用”,” 隔开。
       

        getline 指令 
        getline var < file,file为数据文件,变量var是数据存放的变量,var省略时,数据存放到$0。
        getline var   pipe  变量 ,var省略时,数据存放到$0中。
        getline 一次读取一行资料,若读取成功则return 1,若读取失败则return -1, 若遇到文件结束(EOF), 则return 0

       close  指令 该指令用以关闭一个打开的文件,或pipe
        范例:[root@myfreelinux pub]# cat reformat3.awk
    #!/bin/bash
    awk ‘BEGIN{
    FS=”[ \t:]+”;
    “date”|getline;
    print “Today is”,$2,$3 > “today_result3″;
    close(“today_result3″);
    }
    {
    arrival=HM_TO_M($2,$3);
    printf(“%s\t\t%s:%s %s\n”,$1,$2,$3,arrival>”480″?”*”:“ ”)|“sort -k 1 >> today_result3″;
    total+=arrival;
    }
    END{
    close(“sort -k 1 >> today_result3″);
    printf(“Average arrival time:  %d:%d\n”,total/NR/60, total/NR%60) >> “today_result3″;
    close(“today_result3″);
     }
    function HM_TO_M(hour,min){ return hour*60 + min }’ $*

         说明:1、上例中,一开始执行print “Today is”,$2,$3 > “today_result3″;指令输出今天的月份和日期,使用了I/O 的数据重定向( > )将数据转输出到today_result3,所以today_result3处于打开状态
        2、printf(“%s\t\t%s:%s %s\n”,$1,$2,$3,arrival>”480″?”*”:” “)不停的将输出的资料送往pipe(|),awk 在程序在结束时会呼叫shell,使用指令“sort -k 1 >> today_result3″来处理管道中的数据。而不是将数据输出到管道的时候就开始排序,这一点和Unix 中pipe 的用法不完全相同。
        3、最后希望在文件的末尾加上“Average arrival time”,但此时,Shell还没有执行“sort -k 1 >> today_result3″,所以数据行排序结果还没有写入today_result3中,或者可以认为是today_result3处于打开状态,所以awk应该提前通知Shell执行命令“sort -k 1 >> today_result3″,来处理pipe中的资料。awk 中这个动作称为close pipe,是由执行close ( “shell  command” )来完成。需要注意的是close( )指令中的shell command 需与”|”后方的shell command 完全相同(一字不差),比较好的方法是先将该字串定义一个简短的变量,程序中再以此变量代替该shell  command
        4、为什么执行close(“today_result3”)?这是因为sort完后的资料也将写到today_result3中,这个文件正为awk所打开使用(write)中,所以awk程序中要先关闭today_result3,以免造成因二个进程同时打开一个文件进行输出(write)产生的错误。
         5、close使用的时机是:在第二次写入前,应该关闭前一次写入时打开的文件,close的时候一定于上次打开文件是的打开方式相同。

        system 指令
        该指令用来执行Shell上的command。
        比如:
        path=/etc/local/apache2
        system( “rm -rf” path)
        说明:
        system(“字符串”)指令接受一个字符串当成Shell 的命令,上例中,使用一个字串常数”rm -rf” 连接(concate)一个变量path,形成Shell 执行命令的格式,Shell实际执行的命令是“rm -rf /etc/local/apache2”。

          “|” pipe指令
         “|” 配合awk 输出指令,可以把输出到标准输出即屏幕的资料继续转送给管道后面,作为管道后面的标准输入。”|”配合awk的getline指令,可呼叫Shell执行某一命令,再将getline指令所得到的资料读进awk 程序中。
         例如:
    “date”|getline;
     print “Today is”,$2,$3 > “today_result3″;可参考6.2程序例子部分。

        awk 释放所占用内存的指令
        awk程序中常使用数组(Array)来存储大量数据,delete 指令可以用来释放数组所占用的内存空间。
        比如:for( any in X_arr )     delete X_arr[any] ,需要注意的是:delete 指令一次只能释放数组中的一个元素.。

        awk 中的数学运算符(Arithmetic Operators)
        +(加), -(減), *(乘), /(除), %(求余数), ^(指数) 与C 语言中用法相同

        awk 中的赋值运算符(Assignment Operators)
        =, +=, -=, *= , /=, %=, ^=
         x += 5 的意思是x = x + 5, 其余类推,其实和C语言中的用法相同

        awk 中的条件运算符(Conditional  Operator)
        语法: 判断条件? value1 :value2 
        如果判断条件成立(true) 则返回value1,否则返回value2,这个语句也就是C语言中的三元运算符(?:)

        awk 中的逻辑运算符(Logical Operators)
        &&( and ), ||(or), !(not),正则表达式中使用”|” 表示||,比较容易混淆

        awk 中的关系运算符(Relational Operators)
         >, >=, <, < =, ==, !=, ~, !~

        awk 中其它的运算符
        +(正号),-(负号),  ++(自加),–(自减)

        awk 中各运算符的运算级
        按优先高低排列:    
         $(栏位运算元,例如:i=3; $i表示第3栏);
        ^(指数运算) ;
        + ,- ,! (正,负号,及逻辑上的 not);    
        * ,/ ,% (乘,除,余数) ;   
         + ,-    (加,減) ;
        >, >  =,< , < =, ==, != (关系运算符);
         ~, !~   (match, not match) ;
        && (逻辑and)    
       ||  (逻辑上的 or )    
        ? :     (条件运算符)
        = , +=, -=,*=, /=, %=, ^= (赋值运算符)

    评论已关闭。