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がメモリに穴を挿入することを決定すると、「奇妙な」順序が発生します。

ちなみに、これは公式文書で説明されています。 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ません。)mu

したがって、整数インデックス配列の場合:

$ 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

どちらの場合にも記載されている問題は、白フクロウの答え配列の繰り返しを考慮する必要があります。

関連情報