代码之家  ›  专栏  ›  技术社区  ›  cobp

多维数组的awk数组迭代

  •  17
  • cobp  · 技术社区  · 14 年前

    awk为数组处理提供关联索引。一维数组的元素可以迭代:

    例如

    for(index in arr1)
      print "arr1[" index "]=" arr1[index]
    

    但是这种方法是如何处理二维数组的呢?下面给出的语法是否有效?

    for(index1 in arr2)
    for(index2 in arr2)
       arr2[index1,index2]     
    
    5 回复  |  直到 7 年前
        1
  •  34
  •   Dennis Williamson    13 年前

    awk通过将索引与子类变量(0x1C)中的字符连接来伪造多维数组。您可以使用 split 像这样(基于 info gawk 文件):

    awk 'BEGIN { OFS=","; array[1,2]=3; array[2,3]=5; array[3,4]=8; 
      for (comb in array) {split(comb,sep,SUBSEP);
        print sep[1], sep[2], array[sep[1],sep[2]]}}'
    

    输出:

    2,3,5
    3,4,8
    1,2,3
    

    但是,可以使用嵌套for循环在数字索引数组上迭代:

    for (i = 1; i <= width; i++)
        for (j = 1; j < = height; j++)
            print array[i, j]
    

    另一个值得注意的信息来自 GAWK manual :

    要测试多维数组中是否存在特定的索引序列,请使用用于一维数组的相同运算符(in)。将整个索引序列写在括号中,用逗号分隔,作为左操作数:

         (subscript1, subscript2, ...) in array
    
        2
  •  5
  •   psmears Touffy    14 年前

    不,语法

    for(index1 in arr2) for(index2 in arr2) {
        print arr2[index1][index2];
    }
    

    不起作用。awk并不真正支持多维数组。如果你做类似的事情

    x[1,2] = 5;
    

    将两个索引(1和2)连接起来,形成一个字符串,由 SUBSEP 变量。如果这等于“*”,那么您将具有与

    x["1*2"] = 5;
    

    默认值为 子SEP 是非打印字符,对应于ctrl+\。您可以通过以下脚本看到这一点:

    BEGIN {
        x[1,2]=5;
        x[2,4]=7;
        for (ix in x) {
            print ix;
        }
    }
    

    运行此命令将提供:

    % awk -f scriptfile | cat -v
    1^\2
    2^\4
    

    因此,为了回答您的问题-如何迭代多维数组-只需使用一个 for(a in b) 循环,但您可能需要一些额外的工作来拆分 a 进入其 x y 部分。

        3
  •  3
  •   JJoao    8 年前

    的当前版本 呆呆地 (GNU AWK,默认为 Linux,可以安装在任何地方),有真正的多维数组。

    for(b in a)
       for(c in a[b])
          print a[b][c], c , b
    

    另请参见函数 isarray()

        4
  •  2
  •   Merlin    8 年前

    我将提供一个示例,说明如何在工作处理查询数据时使用它。假设您有一个提取文件,其中包含按产品类别和客户ID划分的事务:

    customer_id  category  sales
    1111         parts     100.01
    1212         parts       5.20
    2211         screws      1.33
    ...etc...
    

    使用awk可以方便地计算购买产品的不同客户总数:

    awk 'NR>1 {a[$1]++} END {for (i in a) total++; print "customers: " total}' \ 
    datafile.txt
    

    然而,计算每个类别中购买的不同客户的数量表明,这是一个二维数组:

    awk 'NR>1 {a[$2,$1]++} 
          END {for (i in a) {split(i,arr,SUBSEP); custs[arr[1]]++}
               for (k in custs) printf "category: %s customers:%d\n", k, custs[k]}' \
    datafile.txt
    

    增加 custs[arr[1]]++ 工作是因为每个类别/客户ID对作为awk使用的关联数组的索引是唯一的。

    事实上,我用的是GNUawk,它更快而且可以 array[i][j] 如D.威廉姆森所说。但我想确定我可以用标准的锥子来做这个。

        5
  •  0
  •   Bob Makowski    7 年前

    awk(1)最初被设计为(部分)C语言的教学工具,而多维数组在c和awk(1)中几乎永远都存在。因此,POSIX IEEE1003.2标准化了它们。

    若要了解语法和语义,请创建以下名为“test.awk”的文件:

    BEGIN {
      KEY["a"]="a";
      KEY["b"]="b";
      KEY["c"]="c";
      MULTI["a"]["test_a"]="date a";
      MULTI["b"]["test_b"]="dbte b";
      MULTI["c"]["test_c"]="dcte c";
    }
    END {
      for(k in KEY) {
        kk="test_" k ;
        print MULTI[k][kk]
      }
      for(q in MULTI) {
        print q
      }
      for(p in MULTI) {
        for( pp in MULTI[p] ) {
          print MULTI[p][pp]
        }
      }
    }
    

    并使用以下命令运行:

    awk -f test.awk /dev/null
    

    您将得到以下输出:

    date a
    dbte b
    dcte c
    a
    b
    c
    date a
    dbte b
    dcte c
    

    至少在Linux Mint 18肉桂64位4.4.0-21-通用37 Ubuntu SMP上