用于多维数组的awk数组迭代

时间:2010-06-17 09:55:37

标签: arrays awk associative-array

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

e.g。

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

但是这种二维数组怎么做?下面给出了哪种语法?

for(index1 in arr2)
for(index2 in arr2)
   arr2[index1,index2]     

5 个答案:

答案 0 :(得分:35)

AWK通过将索引与SUBSEP变量(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

答案 1 :(得分:5)

不,语法

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

不起作用。 Awk并不真正支持多维数组。它做了什么,如果你做了像

这样的事情
x[1,2] = 5;

是连接两个索引(1&amp; 2)以生成一个字符串,用SUBSEP变量的值分隔。如果这等于“*”,那么你将具有与

相同的效果
x["1*2"] = 5;

SUBSEP的默认值是非打印字符,对应于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 1}}和y部分。

答案 2 :(得分:3)

当前版本的 gawk (gnu awk,默认为 linux,并且可以随处安装),具有真正的多维数组。

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

另见函数isarray()

答案 3 :(得分:2)

我将提供一个示例,说明如何在处理查询数据的工作中使用它。假设您有一个完整的产品类别和客户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]]++的增量有效,因为每个category / customer_id对都是唯一的,作为awk使用的关联数组的索引。

事实上,我使用的gnu awk更快,可以像D. Williamson所提到的那样array[i][j]。但我想确保我能用标准的awk做到这一点。

答案 4 :(得分:1)

awk(1)最初设计 - 部分 - 是C语言的教学工具,多维数组几乎都是C和awk(1)。因此POSIX IEEE 1003.2标准化了它们。

要探索语法和语义,如果您创建名为&#34; test.awk&#34;的以下文件:

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 Cinnamon 64-bit 4.4.0-21-generic#37-Ubuntu SMP