AWK : 记录文件数据处理的利器


        这篇文章介绍 AWK 。 它是记录文件数据处理的利器。为什么会这样呢? 

        AWK 隐式地提供了如下功能: 

        (1) 打开每一个文件并读取每一行;对于每一行,根据字段分隔符和行分隔符分割行和字段,并保存文件、行、字段信息; 

        (2) 对每一行进行条件判断和模式匹配,若结果为真则执行相应操作;

        (3) 实际上,提供了记录文件数据处理的框架, 只需要程序员填写条件及操作即可。

                       for each file 

                              for each line 

                                       for each pattern 

                                               if (IsConditionTrue(line, pattern))    do   givenOperation


             AWK 程序结构:

                     BEGIN { init() }    // 只执行一次, 多用于初始化; 

                     PATTERN1   { OPERATION1 }    // 对于每个文件的每一行进行判断, 若模式PATTERN1 为真, 则执行操作 OPERATION1

                     ...

                     PATTERNn   { OPERATIONn }   // 对于每个文件的每一行进行判断, 若模式PATTERNn 为真, 则执行操作 OPERATIONn

                     END  { clean() }    //  只执行一次, 多用于清理工作。

 

             有了这样的框架, 记录文件的数据处理还有多少困难呢?  由于 AWK 特殊的程序处理方式, 特别适合于从筛选满足条件的记录行。


             例子一: 

             某个 src.java 文件中含有如下代码:            

    public final static String CLUNUMREPORT_ALIAS = "clunumrep";
    public final static String CLUNUMREPORT_PREFIX = "clunumrep.";
    
    public final static String TOTAL_KEY = "total";
    public final static String STOPPED_KEY = "stopped";
    public final static String RUNNING_KEY = "running";
    public final static String DESTROYED_KEY = "destroyed";
    public final static String NEW_KEY = "new";
    
    
    public final static String REPORT_NUM_HOLE_KEY_RES="REPORT_NUM_HOLE_KEY";
    public final static String REPORT_MON_CIN_AVG_KEY_RES="REPORT_MON_CIN_AVG_KEY";
    public final static String REPORT_MON_INTER_KEY_RES="REPORT_MON_INTER_KEY";
    public final static String VM_INTER_KEY_RES="VM_INTER_KEY";

 

             现在我期望能够将类似 TOTAL_KEY = "total"; 的值对提取出来以方便查看。 用 AWK 怎么做呢 ? 

                awk ' NF==5 { print $5 } ; NF==7 { print $5, $6, $7} ' src.java  >  result.txt 

                OK .  就这么简单。  NF==5 { print $5 } 表示 行的字段数目为 5 时打印第 5 个字段。 默认以空白符为字段分割符。 可以通过 -F 选项设置。


                例子二:  假设有这样的数据文件 src.txt :

                 name     no height this last 
                 zhangsan 1  159    95    92 
                 lisi            3  167    88    91
                 wangwu   6  172    82    84

                 this 表示此次的成绩, last 表示上次的成绩。 要找出成绩进步的同学,也就是说 this 值大于 last .  只要

 

                 awk ' $4 > $5 { print } '  src.txt 


               例子三:   找出当前目录及子目录下的所有 .java 文件中含有 vm_monitor 模式字符串的记录行,并打印文件、行信息。 

               find . -name '*.java' | xargs awk ' $0 ~ /vm_monitor/ { printf "%s : Line %s :\n%s \n" , FILENAME, FNR, $0 } ' | sed 's/^[[:space:]]\{1,\}/ /' | fmt -w 75


              够快捷的吧 ? 所以说, 掌握一些重要的 Linux 工具 (Windows 下也可获得!cygwin ), 日常任务其实不需要像 Java / Python 这样重型的武器, 连 C 都不算轻量级了。 

 

               一个简单的 awk 程序: 计算 /etc/passwd 第三个字段的和数。

              使用: awk -f calc.awk /etc/passwd

BEGIN {
     FS=":"
     total=0
}
{
     if ($3 < 1000000) {
         total += $3
         num[NR] = $3
     }
}
END {
    print "ARGC=", ARGC;
    for(k in ARGV) {
         print k, "=", ARGV[k];
    }
    print "File: ", FILENAME
    for (i=1; i<=FNR; i++) {
         printf("%d %s ", num[i] , (i==FNR) ? "" : "+")
    }
    print " = ", total
}

 

posted @ 2012-09-26 20:46  琴水玉  阅读(217)  评论(0编辑  收藏  举报