Linux三剑客:awk

awk简介

 awk程序设计语言 允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表等功能。awk 借鉴了某些语言的一些精华,如 C 语言等。在 linux 系统日常处理工作中,发挥很重要的作用,掌握了 awk将会使你的工作变的so easy。

awk语言的最基本功能是在文件或者字符串中基于指定规则浏览和抽取信息,awk抽取信息后,才能进行其他文本操作。完整的awk脚本通常用来格式化文本文件中的信息。

通常,awk是以文件的一行为处理单位的。awk每接收文件的一行,然后执行相应的命令,来处理文本。

语法格式

awk [options] 'script' var=value file(s) 
awk [options] -f scriptfile var=value file(s) 

常用命令选项

  • -F fs fs 指定输入分隔符,fs可以时字符串或正则表达式

  • -v var=value 赋值一个用户定义变量,将外部变量传递给awk

  • -f scriptfile 从脚本文件中读取awk命令

awk脚本

awk脚本是由模式和操作组成的。

模式与操作

模式

模式可以是以下任意一种:

  • 正则表达式:使用通配符的扩展集

  • 关系表达式:使用运算符进行操作,可以是字符串或数字的比较测试

  • 模式匹配表达式:用运算符(匹配)和~!不匹配

  • BEGIN 语句块, pattern语句块, END语句块

操作

操作由一个或多个命令、函数、表达式组成,之间由换行符或分号隔开,并位于大刮号内,主要部分是:变量或数组赋值、输出命令、内置函数、控制流语句。

awk脚本基本格式

awk 'BEGIN{ commands } pattern{ commands } END{ commands }' file 

一个awk脚本通常由BEGIN, 通用语句块,END语句块组成,三部分都是可选的。 脚本通常是被单引号或双引号包住

awk 'BEGIN{ i=0 } { i++ } END{ print i }' filename  

awk执行过程分析

  • 第一步: 执行BEGIN { commands } pattern 语句块中的语句

    BEGIN语句块:在awk开始从输入输出流中读取行之前执行,在BEGIN语句块中执行如变量初始化,打印输出表头等操作。

  • 第二步:从文件或标准输入中读取一行,然后执行pattern{ commands }语句块。它逐行扫描文件,从第一行到最后一行重复这个过程,直到全部文件都被读取完毕。

    pattern语句块:pattern语句块中的通用命令是最重要的部分,它也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行。{ }类似一个循环体,会对文件中的每一行进行迭代,通常将变量初始化语句放在BEGIN语句块中,将打印结果等语句放在END语句块中。

  • 第三步:当读至输入流末尾时,执行END { command }语句块

    END语句块:在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块。

    AWK内置变量

  • $n : 当前记录的第n个字段,比如n为1表示第一个字段,n为2表示第二个字段。

  • $0 : 这个变量包含执行过程中当前行的文本内容。

  • FIELDWIDTHS : 字段宽度列表(用空格键分隔)。

  • FILENAME : 当前输入文件的名。

  • NR : 表示记录数,在执行过程中对应于当前的行号

  • FNR : 同NR :,但相对于当前文件。

  • FS : 字段分隔符(默认是任何空格)。

  • IGNORECASE : 如果为真,则进行忽略大小写的匹配。

  • NF : 表示字段数,在执行过程中对应于当前的字段数。 print $NF打印一行中最后一个字段

将外部变量值传递给awk

  • 借助 -v 选项,可以将来自外部值(非stdin)传递给awk

    VAR=10000
    echo | awk -v VARIABLE=$VAR '{ print VARIABLE }'

  • 定义内部变量接收外部变量

    var1="aaa"
    var2="bbb"
    echo | awk '{ print v1,v2 }' v1=$var1 v2=$var2

  • 使用"'把shell变量包起来,即"'$var'";注意是“双引号+单引号+shell变量+单引号+双引号”的格式

    var="abc"

    awk 'BEGIN{print "'$var'"}'

  • 使用"'"把shell变量包起来,即"'"$var"'";注意是“双引号+单引号+双引号+shell变量+双引号+单引号+双引号”的格式。

    如果变量的值中包含空格,为了shell不把空格作为分隔符,则应使用这种方法。

    var="this a test"

    awk 'BEGIN{print "'"$var"'"}'

  • export变量,然后在awk中使用ENVIRON["var"]形式获取环境变量的值

    var="this a test"; export var;

    awk 'BEGIN{print ENVIRON["var"]}'  

    awk运算

  • 算术运算:(+,-,*,/,&,!,……,++,--)

    所有用作算术运算符进行操作时,操作数自动转为数值,所有非数值都变为0

  • 赋值运算:(=, +=, -=,*=,/=,%=,……=,**=)

  • 逻辑运算符: (||, &&)

  • 关系运算符:(<, <=, >,>=,!=, ==)

  • 正则运算符:(~,~!)(匹配正则表达式,与不匹配正则表达式)

    awk 'BEGIN{a="100testa";if(a ~ /^100*/){print "ok";}}'
    ok

    next 语句

    awk中next语句使用:在循环逐行匹配,如果遇到next,就会跳过当前行,直接忽略下面语句。而进行下一行匹配。net语句一般用于多行合并:

    awk 'NR%2==1{next}{print NR,$0;}' text.txt
    说明: 当记录行号除以2余1,就跳过当前行。下面的print NR,$0也不会执行。下一行开始,程序有开始判断NR%2值。这个时候记录行号是:2 ,就会执行下面语句块:print NR,$0

    文件操作

  • 打开文件 open("filename")

  • 关闭文件 close("filename")

  • 输出到文件 重定向到文件,如echo | awk '{printf("hello word!n") > "datafile"}'

     

循环结构

for循环

for(变量 in 数组)  
{语句} 
 
for(变量;条件;表达式) 
{语句} 

while循环

while(表达式) 
    {语句} 

do...while循环

do  
{语句} while(条件) 

其他相关语句

  • break:退出程序循环

  • continue: 进入下一次循环

  • next:读取下一个输入行

  • exit:退出主输入循环,进入END,若没有END或END中有exit语句,则退出脚本。

数组

在awk中数组叫做关联数组(associative arrays)。awk 中的数组不必提前声明,也不必声明大小。数组元素用0或空字符串来初始化,这根据上下文而定。

awk 'BEGIN{ 
        Array[1]="lee"  
        Array[2]="gwin" 
        Array["first"]="www"  
        Array["last"]="name"  
        Array["birth"]="1992" 
         
        info = "it is a test"; 
        lens = split(info,tA," "); 
        for(item in tA){
            print tA[item];
          } 
        for(i=1;i<=lens;i++){
            print tA[i];
          } 
        print length(tA[lens]); 
        } 
        { 
        print "item in array"; 
        for(item in Array) {
            print Array[item]
        }; 
        print "print in i++"; 
        for(i=1;i<=length(Array);i++) {
            print Array[i]};   
        }' 
  • 获取数组长度

awk 'BEGIN{ 
        info="it is a test"; 
        lens=split(info,tA," ");    #使用split函数获取数组长度 
        print length(tA),lens;      #使用length函数获取数组长度(版本有要求) 
        }' 
  • 输出数组内容

    • 有序输出 for...in

      因为数组时关联数组,默认是无序的

    • 无序输出 for(i=1;i<l=ens;i++)

      数组下标从1开始

  • 判断键值是否存在
#判定方法:使用 if ( key in array) 判断数组中是否包含 键值 
awk 'BEGIN{ 
        tB["a"]="a1"; 
        tB["b"]="b1"; 
        if( "c" in tB){ 
            print "ok"; 
        }; 
        for(k in tB){ 
            print k,tB[k]; 
        }}' 
  • 删除键值
    delete array[key]可以删除,对应数组key的,序列值。

    awk 'BEGIN{ 
            tB["a"]="a1"; 
            tB["b"]="b1"; 
            delete tB["a"]; 
            for(k in tB){ 
                print k,tB[k]; 
            }}' 

    内置函数

    算术函数

    格式 描述
    atan2( y, x ) 返回 y/x 的反正切。
    cos( x ) 返回 x 的余弦;x 是弧度。
    sin( x ) 返回 x 的正弦;x 是弧度。
    exp( x ) 返回 x 幂函数。
    log( x ) 返回 x 的自然对数。
    sqrt( x ) 返回 x 平方根。
    int( x ) 返回 x 的截断至整数的值。
    rand( ) 返回任意数字 n,其中 0 <= n < 1。
    srand( [expr] ) 将 rand 函数的种子值设置为 Expr 参数的值,或如果省略 Expr 参数则使用某天的时间。返回先前的种子值。

猜你喜欢

转载自blog.csdn.net/u012460314/article/details/84338966