是否可以在awk中将项附加到数组而不指定索引?

时间:2012-05-25 17:04:43

标签: awk gawk

我意识到awk有关联数组,但我想知道是否有一个等同于此的awk:

http://php.net/manual/en/function.array-push.php

明显的解决方法是说:

array[$new_element] = $new_element

然而,这似乎不那么可读,而且比他们需要的更加狡猾。

3 个答案:

答案 0 :(得分:11)

我不认为awk中的数组长度是立即可用的(至少在我使用的版本中没有)。但你可以简单地保持长度然后做这样的事情:

array[arraylen++] = $0;

然后通过相同的整数值访问元素:

for ( i = 0; i < arraylen; i++ )
   print array[i];

答案 1 :(得分:8)

gawk中,您可以找到length(var)数组的长度,因此烹饪自己的功能并不是很难。

function push(A,B) { A[length(A)+1] = B }

请注意这个讨论:http://objectmix.com/awk/361598-gawk-length-array-question.html - 我现在可以访问的所有地方都有gawk 3.1.5所以我无法正确测试我的功能,呃。但这是一个近似值。

vnix$ gawk '# BEGIN: make sure arr is an array
>   BEGIN { delete arr[0] }
>   { print "=" length(arr); arr[length(arr)+1] = $1;
>     print length(arr), arr[length(arr)] }
>   END { print "---";
>     for (i=1; i<=length(arr); ++i) print i, arr[i] }' <<HERE
> fnord foo
> ick bar
> baz quux
> HERE
=0
1 fnord
=1
2 ick
=2
3 baz
---
1 fnord
2 ick
3 baz

答案 2 :(得分:1)

正如其他人所说,awk没有提供开箱即用的功能。您的“hackish”解决方法可能适用于某些数据集,但不适用于其他数据集。考虑您可以将相同的数组值添加两次,并希望它在数组中表示两次。

$ echo 3 | awk 'BEGIN{ a[1]=5; a[2]=12; a[3]=2 }
>   { a[$1] = $1 }
>   END {print length(a) " - " a[3]}'
3 - 3

最好的解决方案可能是数据在数组中的通知,但这里有一些想法。

首先,如果您确定您的索引将始终为数字,将始终从1开始,并且您永远不会删除数组元素,那么trie的A[length(A)+1]="value"建议可能适合您。但是如果删除了一个元素,那么下一次写入可能会覆盖你的最后一个元素。

如果您的索引无关紧要,并且您不担心使用长按键浪费空间,则可以使用足够长的随机数来减少碰撞的可能性。快速和快速脏选项可能是:

srand()
a[rand() rand() rand()]="value"

请记住使用srand()进行更好的随机化,并且不要相信rand()来生成实际的随机数。这在很多方面都不是完美的解决方案,但它具有成为单行代码的优势。

如果您的密钥是数字但可能是稀疏的,就像打破tripleee解决方案的示例一样,您可以在推送功能中添加一个小搜索:

function push (a, v,     n) {
  n=length(a)+1
  while (n in a) n++
  a[n]=v
}

while循环可确保您分配未使用的索引。此函数还与使用非数字索引的数组兼容 - 它分配数字键,但它并不关心那些已存在的键。

请注意,awk不保证数组中元素的顺序,因此您将“将项目推送到数组末尾”的想法是错误的。你将这个元素添加到数组中,但是当你单步执行for循环时,不能保证它会出现在最后。

$ cat a
#!/usr/bin/awk -f

function push (a, v,     n) {
  n=length(a)+1
  while (n in a) n++
  a[n]=v
}

{
  push(a, $0)
}

END {
  print "length=" length(a)
  for(i in a) print i " - " a[i]
}

$ printf '3\nfour\ncinq\n' | ./a
length=3
2 - four
3 - cinq
1 - 3