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

问题描述 投票:18回答:5

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

EG

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

但是这种二维数组怎么做呢?下面给出的那种语法有用吗?

for(index1 in arr2)
for(index2 in arr2)
   arr2[index1,index2]     
arrays awk associative-array
5个回答
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

5
投票

不,语法

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

不行。 Awk并不真正支持多维数组。它做了什么,如果你做了类似的事情

x[1,2] = 5;

是连接两个索引(1和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分成xy部分。


3
投票

当前版本的gawk(gnu awk,默认在linux中,可以安装到你想要的任何地方),具有真正的多维数组。

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

另见函数isarray()


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做到这一点。


1
投票

awk(1)最初设计 - 部分 - 是C语言的教学工具,多维数组几乎都是C和awk(1)。因此POSIX IEEE 1003.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 Cinnamon 64-bit 4.4.0-21-generic#37-Ubuntu SMP上

© www.soinside.com 2019 - 2024. All rights reserved.