为什么 gawk asort() 的输出不按顺序排列?

为什么 gawk asort() 的输出不按顺序排列?

我尝试了这个gawk命令:

# gawk 'BEGIN{
> var["a"] = 1
> var["g"] = 2
> var["m"] = 3
> var["u"] = 4
> asort(var, test)
> for (i in test)
> print "Index:",i," - value:",test[i]
> }'

并会得到以下输出:

索引:4 - 值:4

索引:1 - 值:1

索引:2 - 值:2

索引:3 - 值:3

所以我想知道为什么输出不按如下顺序排列:

指数:1

指数:2

...

因为这是数组值的正确序列

答案1

for (var in array)保证访问数组元素的顺序。

当每个元素存储在内存中时,循环将对其进行迭代,但是如果在存储下一个元素期间,awk 决定在内存中插入一些漏洞 - 您将得到一个“奇怪”的顺序。

BTW,官方文档中是这样描述的: https://www.gnu.org/software/gawk/manual/html_node/Scanning-an-Array.html#index-for-statement-1

因此,如果你想要一个有保证的排序数组,你将不得不使用类似的东西:

element_count = asort(var, test)
for (i=1; i<=element_count; i++)
   print "Index:",i," - value:",test[i]

答案2

我认为asort()更适合由整数索引的数组,因为它用 1 替换索引n,破坏原来的索引。 (正如您在案例中看到的那样,索引a, g, m,u丢失了。)

因此,对于整数索引数组:

$ cat sort.awk
BEGIN {
    printf("original:\n");
    n = split("hello and bye", a)
    for (i = 1; i <= n; i++) {
        printf("%d %s\n", i, a[i])
    }
    printf("sorted:\n");
    n = asort(a, b);
    for (i = 1; i <= n; i++) {
        printf("%d %s\n", i, b[i])
    }
}

$ awk -f sort
original:
1 hello
2 and
3 bye
sorted:
1 and
2 bye
3 hello

如果你的索引本身包含数据,你可能需要这样做asorti();它会创建一个新数组,其中原始键作为值,并从 1 开始索引,以使键按顺序排列:

$ cat sort2.awk
BEGIN {
    d["foo"]=11;
    d["bar"]=22;
    d["doo"]=33;
    n = asorti(d, p);
    for (i = 1; i <= n; i++) {
        printf("%d %s %s\n", i, p[i], d[p[i]])
    }
}
$ awk -f sort2.awk
1 bar 22
2 doo 33
3 foo 11

在这两种情况下,中描述的问题白猫头鹰的回答需要考虑对数组进行迭代。

相关内容