• awk中的数组


    awk中的数组
    20130110

    awk作为一门脚本语言,支持的数据类型主要是简单变量和数组变量。awk中的数组与传统的C和java中的数组不同,更类似于C++ STL中的map或python中的dict,是关联式数组,通过关联关系将key和value结合起来。并且它并不限制key和value的类型,可以在一个数组中混合使用多种类型的key和value(尽管可能不常这么用)。awk中的变量在使用之前是不需要声明的,在第一次使用时确定它的类型,并且以后不再改变。所以如果一个变量arr第一次被当做数组来使用,那么以后就不能在用作简单变量。假定arrary是一个数组变量,如果key不在array中,那么arrary[key]将返回一个空串;如果key在array中,则返回对应的变量arrary[key]。awk可以通过关键字in来判断key是否在数组中出现。并且可以通过for(key in array)的形式来遍历数组中的元素.

    awk中数组的排序问题

    awk中的数组是关联式的,因此在使用for(key in array)的方式进行遍历的时候,输出的顺序并不是按照key进行排序输出的,因为awk中的数组内部采用hash的方式实现,因此输出的顺序能是不确定的。当需要按照某种顺序输出元素时,需要使用到asort和asorti函数来辅助。

    asort的原型为:
    asort(array1[, arrary[2]])
    asort是将数组的value值进行排序,并且返回数组中元素的个数。如果采用asort(array)这种简略方式,那么重排之后的数据将会保存在array中,但是关联关系将会被取消,下面是一个简单的例子:
    [c-sharp] view plaincopy
    "wang" => 15 1 => 33
    "lim" => 14 2 => 19
    "zhuang"=> 19 asort() -> 3 => 15
    "han" => 334 4 => 14
    "feng" => 11 5 => 11
    排序结束之后,原先的关联关系被取消,取而代之的是index与value的对应关系。

    如果需要对key进行排序,那么可以使用asorti函数,该函数的原型为:
    asorti(array1[, array2])
    asorti将数组的key值进行排序,并返回数组中元素的个数。与asort类似,如果使用asorti(array)这种简略的方式,那么排序后的key值成为value值,原先的关联关系被破坏。下面是一个简单的例子:
    [c-sharp] view plaincopy
    "wang" => 15 1 => feng
    "lim" => 14 2 => han
    "zhuang"=> 19 asort() -> 3 => lim
    "han" => 33 4 => wang
    "feng" => 11 5 => zhuang

    如过想要保留原先的关联关系,则可以使用asorti(array1, array2)这种形式,排序后的key被保存在array2数组中。
    假定有如下的问题:有一个文件包含了一组人员的信息,格式的类型为:
    [cpp] view plaincopy
    Name Age Height Weight
    wanger 18 173 74
    liusan 20 177 80
    zhaojun 24 167 49
    tianjing 30 179 75
    haobo 28 171 65
    我们想要按照其中的某一项(比如身高)进行排序,当然是用sort工具就可以实现,现在我们使用awk来实现。下面是按照身高对所有的条目进行排序的代码:
    [cpp] view plaincopy
    {
    arrary[$2] = $0
    }
    END{
    asorti(arrary, height);
    for(h in height)
    {
    print arrary[height[h]];
    }
    }

    awk中hash

    需求:
    2个文件列表a[n],b[n]。分别打出两个文件不同的行,保存在不同的文件里

    方法1:读入a的每一行,分别到b[n]中grep。思路简单,但效率低到抓狂
    方法2:comm ,不清楚原理是什么,但效率也很低。。。
    方法3:awk+hash(冒泡算法吧?)

      以找出只在a[n]中存在的行为例:设一个外层循环,分别取a[n]中的每一个文件$file_a;设一个内循环,使$file_a与每一个b[n]文件$file_b比较.每一次将$file_a中存在,$file_b中不存在的行赋给$tmp,再用$tmp代替$file_a在下一个$file_b中搜索,所以随着过滤过的$file_b越多,$tmp中的行将越来越少,所有$file_b过滤后,就保证了$file_a中的所有与$file_b中相同的行已被过滤。

      唉,实际应用和学校里编程就是不一样:学校里能实现的算法就是好算法;实际上还要考虑效率问题。在大数据量的应用中,我第一版的程序能跑上1个星期,优化到第三版时才能几个小时搞定。

    for file_a in a[n]
    do
    cp $file_a tmp
    for file_b in b[n]
    do
    awk '
    BEGIN{file=0;}
    FNR1{file++;}
    file
    1{hash[$0]=1;}
    file2{if($0 in hash)hash[$0]=0;}
    END{for(key in hash)
    {if(hash[key]
    1)print key;}}
    ' $tmp $file_b >new_in_a
    mv $new_in_a $tmp
    done
    cat $tmp >>$final_result
    done

  • 相关阅读:
    计算机网络中协议相关的问题(转)
    Vs2013打开项目时,一直处理等待状态,并显示“Microsoft Visual Studio正忙”的提示窗,处理方法(转)
    ASP.NET Core 2.2 十九. Action参数的映射与模型绑定(转)
    ASP.NET Core 2.2 十八.各种Filter的内部处理机制及执行顺序(转)
    ASP.NET Core 2.2 : 十七.Action的执行(Endpoint.RequestDelegate后面的故事)(转)
    ASP.NET Core 2.2 : 十六.扒一扒新的Endpoint路由方案(转)
    【Leetcode】771. Jewels and Stones
    【Leetcode】50. Pow(x, n)
    【Leetcode】 328. Odd Even Linked List
    【leetcode】59.Spiral Matrix II
  • 原文地址:https://www.cnblogs.com/chanix/p/12738228.html
Copyright © 2020-2023  润新知