• awk 留底


     
     
    因为经常做awk编码,而且跨过一段时间就容易忘记,故在此做个留底。便于翻阅。——后期会在这个页面不断补充!
     

    常用常量
     
     
    属性 描述
    NR  已读入的总记录数
     ARGIND  当前被处理参数标志 
    FILENAME  当前输入文件名
    FS   输入域分隔符,默认为一个空格
    RS   输入记录分隔符
    NF  当前记录里域个数
     SUBSEP 下标分隔符 "34" 
     

    获取日期
     
    strftime("%Y-%m-%d", systime())

    加载awk文件方式
     
     awk -v "file_name=`basename $file`" -f cut_online.awk $file
     

    处理多个文件的时候,区分文件
     
     
    区分:
     
     

    数组操作
     
     
     awk的数组,一种关联数组(Associative Arrays),下标可以是数字和字符串。因无需对数组名和元素提前声明,也无需指定元素个数 ,所以awk的数组使用非常灵活。
    首先介绍下几个awk数组相关的知识点:
    <1>建立数组
    array[index] = value :数组名array,下标index以及相应的值value。

    <2>读取数组值

    { for (item in array)  print array[item]} # 输出的顺序是随机的
    {for(i=1;i<=len;i++)  print array[i]} # Len 是数组的长度

    <3>多维数组,array[index1,index2,……]:SUBSEP是数组下标分割符,默认为“34”。可以事先设定SUBSEP,也可以直接在SUBSEP的位置输入你要用的分隔符,如:

    awk 'BEGIN{SUBSEP=":";array["a","b"]=1;for(i in array) print i}'
    a:b
    awk 'BEGIN{array["a"":""b"]=1;for(i in array) print i}'
    a:b

    但,有些特殊情况需要避免,如:

    awk 'BEGIN{
    SUBSEP=":"
    array["a","b:c"]=1               # 下标为“a:b:c”
    array["a:b","c"]=2               #下标同样是“a:b:c”
    for (i in array) print i,array[i]}'
    a:b:c 2                                 #所以数组元素只有一个。

    <4>删除数组或数组元素: 使用delete 函数

    delete array                     #删除整个数组
    delete array[item]           # 删除某个数组元素(item)

    <5> 排序:awk中的asort函数可以实现对数组的值进行排序,不过排序之后的数组下标改为从1到数组的长度。在gawk 3.1.2以后的版本还提供了一个asorti函数,这个函数不是依据关联数组的值,而是依据关联数组的下标排序,即asorti(array)以后,仍会用数字(1到数组长度)来作为下标,但是array的数组值变为排序后的原来的下标,除非你指定另一个参数如:asorti(a,b)。 

    echo 'aa
    bb
    aa
    bb
    cc' |
    awk '{a[$0]++}END{l=asorti(a);for(i=1;i<=l;i++)print a[i]}'
    aa
    bb
    cc
    
    echo 'aa
    bb
    aa
    bb
    cc' |
    awk '{a[$0]++}END{l=asorti(a,b);for(i=1;i<=l;i++)print b[i],a[b[i]]}'
    aa 2
    bb 2
    cc 1
     
     
    属性描述
    asort  asort对数组进行排序,返回数组长度 
       
       
       
       
       
       
    练习1(分析出每天有多少员工离职?有多少员工入职?)
     
    awk代码(test_log_info.awk)
    BEGIN{
            today = strftime("%Y-%m-%d-%H", systime());
    }
    FILENAME == ARGV[1]{ # 第一个文件 旧记录
            old_user[$1] = $0;
    }
    FILENAME == ARGV[2]{ # 第二个文件 新纪录
            new_user[$1] = $0;
    }
    END{
            log_info = "";
            log_file = log_dir"user_log_info.log."today"";
            for(old_uid in old_user){
                    if(new_user[old_uid] == ""){
                            log_info = log_info"leave user:"old_user[old_uid]"
    ";
                            delete new_user[new_uid];
                    }
            }
    
    
            for(new_uid in new_user){
                    if(old_user[new_uid] == ""){
                            log_info = log_info"add user:"new_user[new_uid]"
    ";
                            delete old_user[new_uid];
                    }
            }
    
            log_info = log_info"old count:"asort(old_user)";new count:"asort(new_user);
            system(" echo '"log_info"' > "log_file);
    }

    分析日志shell脚本(test_log_info.sh)

    #!/bin/bash
    
    yesterday(){
            yy=`date +%Y` #Year yyyy
            mm=`date +%m` #Month mm
            dd=`date +%d` #Day dd
            if [ $dd = "01" ]
            then
                    lm=`expr $mm - 1 `
                    if [ $lm -eq 0 ]
                    then
                            lm=12
                            yy=`expr $yy - 1 `
                    fi
                    echo lm=$lm
                    case $lm in
                         1|3|5|7|8|10|12) Yesterday=31 ;;
                         4|6|9|11) Yesterday=30 ;;
                         2)
                                 if [ ` expr $yy % 4 ` -eq 0 -a `expr $yy % 100 ` -ne 0 -o ` expr $yy % 400 ` -eq 0 ]
                                 then Yesterday=29
                                 else Yesterday=28
                                 fi ;;
    
                    esac
                    mm=$lm
                    Yesterday=$Yesterday
             else
                    Yesterday=`expr $dd - 1 `
             fi
    
             case $Yesterday
                 in 1|2|3|4|5|6|7|8|9) Yesterday='0'$Yesterday
             esac
             case $mm in
                   1|2|3|4|5|6|7|8|9) mm='0'$mm ;;
             esac
    
             Yesterday=$yy"-"$mm"-"$Yesterday"-05"
    }
    yesterday
    Today=`date "+%Y-%m-%d-05"`
    TEMP_DIR="/home/rd/zhoubc/bak/"
    
    awk -v "log_dir="$TEMP_DIR -f test_log_info.awk  $BAKDIR""test2.conf.""$Yesterday  $BAKDIR""test2.conf.""$Today

    调用嵌套的shell文件(test_send.sh)

    #!/bin/bash
    BAKDIR='/home/crontab/send_user/bak/'
    
    source test_log_info.sh

    调用:

    几个技术点:

     shell脚本套用(source)——这样可以公用变量

    source test_log_info.sh

     awk多文件分别处理:

    FILENAME == ARGV[1]{}
    FILENAME == ARGV[2]{}
    案例1:统计每个分类下,样本的中位数
     
     
    数据结构:
    下标从1开始计算。第二列为分类ID,第11类为月日均pv量。
    325	20	230	4918	4	1	64	0	0	64.72	36.9	25	26
    803	25	33	249	4	0	74	0	0	4.0	3.5	3	2
    841	0	566	8624	11	21	269	1	0	527.57	415.6	1331	825
    858	8	498	11569	21	17	477	1	0	1386.29	913.87	2787	2982
    1004	6	221	3222	15	7	176	1	0	900.28	673.36	712	458
    

    相关代码:

    # $11 是月日均pv量
    function ceil(x){
        y = int(x);
        return (x > y ? y + 1 : y)
    }
    # 取中位数
    function get_median(arr){
        len = asort(arr);
        #for(i = 1; i <= len; i++) {
        #    printf("%d	", arr[i]);
        #}
        #printf("
    ");
    
        mid = ceil(len/ 2);
        if(len%2 == 0){
            return ceil((arr[mid] + arr[mid + 1]) / 2);
        }
        #printf("mid=%d
    ", mid);
        return arr[mid];
    }
    
    BEGIN{
    }
    {
        if(!($2 in cardTypeTree)){
            cardTypeTree[$2] = $11;
        } else {
            cardTypeTree[$2] = cardTypeTree[$2]"_"$11;
        }
    }
    END{
        system("rm -f ./parseType.txt")
        for(key in cardTypeTree){
            split(cardTypeTree[key], array, "_")
            printf("%-10s	%d	%-10s
    ", key, length(array), get_median(array))
            system("echo '"key"	"length(array)"	"get_median(array)"' >> ./parseType.txt")
        }
    }
    

     

    执行结果如下:

     

     
    总结
     
       工作中断断续续会用到awk脚本,老是用去搜索太麻烦了,故放在这里,方便日后查阅。如果对你有帮助,就推荐一下!
     
    推荐
     
  • 相关阅读:
    HTTP 常见状态码
    SpringMVC 入门
    Maven 整合SSH框架
    SSH 框架整合总结
    Maven 整合SSH框架之pom.xml
    Maven 入门
    WebService 综合案例
    CXF 框架
    jQuery高级
    JavaScript补充:BOM(浏览器对象模型)
  • 原文地址:https://www.cnblogs.com/baochuan/p/3552370.html
Copyright © 2020-2023  润新知