AWK 简明教程

之前对awk的使用一直停留在截取某列打印出来的水平上,最近简单学习了一下awk,发现这个东西还是比较强大的,这里总结一下.

awk的基本使用

awk是一个非常好的行文本处理器,支持从标准输入接收数据,结果输出至标准输出.比如我们可以这么用:

cat a.txt|awk '{print $2}'

上面这行的意思是将每行的第二列打印出来.默认分隔符是空格或者tab.当然我们可以通过F参数来修改.

cat a.txt|awk -F , '{print $2}'

上面这行就将分隔符改为了逗号.
观察awk后面的部分,可以明显看出,这就是一段脚本.既然是脚本,那么当脚本过长,在命令行直接编写肯定是不够方便的.
所以awk支持指定某一个脚本文件来处理.比如我们可以这么干:
新建一个文件,名字为awktst,内容如下:

{print $2}

我们可以将上面的脚本改为:

cat a.txt|awk -F , -f awktst

awk的基本结构

awk是基于行文本的处理工具,当我们将文本流输入awk的时候,awk其实是在不停的重复处理同一行.其结构主要分为三部分:Begin,body,END.
处理的过程伪码如下:

BEGIN{
     #init something before start text reading
 }
 while((line = readline())!=null){
     body{
         #the main awk process is here
     }
 }
 END{
     #do something after read end
 }

 

我们只需要编写BEGIN,body和END过程就好了.

每部分都用大括号来标识自己的代码块.需要注意的是,awk的变量作用域是全局的,而和代码块没关系.

还是上面的例子,我们可以再将awktst改写的更高端一些:

BEGIN{FS = ","} #FS是awk的一个默认变量,代表标示符
#下面这个其实就是body
{print $2}

我们执行的命令就可以改为:

cat a.txt|awk -f awktst

awk的参数和变量

可以看到,上面我们用到了$2来表示第二列,其实awk在分割上还有两个常用的变量,既
$0 表示整行
$NF 倒数第一列

我们也能自己定义参数,定义很简单:

a = 1
a = 'a'
a = "abcd"
a[b]=c #map形式

awk的语法

awk语法和c/java非常像,下面有个小例子,看一下应该就明白

k1 = "Chris";
k2 = "John";
age[k1] = 30;
age[k2] = 29;
 
for (ke in age){
    if (ke == "Chris"){
        val = age[ke];
        print "Hello Chris , your age is ",val;
    }
}

一个简单的例子:

#这是一个处理java异常日志的小脚本.作用是将今天的异常全部输出.
#java异常文件是一个第一列为日期的时间顺序文件,所以我们只要找到第一个今天的异常,然后将剩下的直接输出即可.

BEGIN {"date +%Y-%m-%d"|getline now;nowStart = 0}
{
    if($1 == now){
        nowStart = 1
    }
    if(nowStart == 1){
        print
    }
 
}

这是另外一个简单的例子

#有文件类似:
name salary age
chris 1000 30
john 1100 24
#我们希望获取薪水总和,平均年龄

BEGIN{
    personCount = 0;
    salarySum = 0;
    ageSum = 0;
    rowCount = 0;
}
{
    if(rowCount != 0 ){#第一行是表头,不处理
        salarySum += $2;
        ageSum += $3;
        personCount ++;
    }
    rowCount ++;
 
}
END{
    print "Total salary is :",salarySum;
    print "Average age is :",(ageSum/personCount);
}
$ cat person | awk -f awktst
Total salary is : 2100
Average age is : 27

发表评论

电子邮件地址不会被公开。 必填项已用*标注