如何在awk中复制多维数组(即数组数组)?

如何在awk中复制多维数组(即数组数组)?,awk,Awk,这个问题的目的是用一个不明显的解决方案发布一个问题的规范答案——复制数组数组(数组数组需要GNU awk) 给定一组数组,如gawk手册中关于以下内容的部分所示: 您将如何编写一个copy_array函数来处理数组数组数组,将现有数组复制到新数组中,这样新复制的数组的walk_array()后续调用将为新数组输出与原始数组相同的值,即: BEGIN { a[1] = 1 a[2][1] = 21 a[2][2] = 22 a[3] = 3 a[4][1][

这个问题的目的是用一个不明显的解决方案发布一个问题的规范答案——复制数组数组(数组数组需要GNU awk)

给定一组数组,如gawk手册中关于以下内容的部分所示:

您将如何编写一个
copy_array
函数来处理数组数组数组,将现有数组复制到新数组中,这样新复制的数组的
walk_array()
后续调用将为新数组输出与原始数组相同的值,即:

BEGIN {
    a[1] = 1
    a[2][1] = 21
    a[2][2] = 22
    a[3] = 3
    a[4][1][1] = 411
    a[4][2] = 42

    walk_array(a, "a")

    copy_array(a, b)

    print "----------"

    walk_array(b, "b")
}
将输出:

a[1] = 1
a[2][1] = 21
a[2][2] = 22
a[3] = 3
a[4][1][1] = 411
a[4][2] = 42
----------
b[1] = 1
b[2][1] = 21
b[2][2] = 22
b[3] = 3
b[4][1][1] = 411
b[4][2] = 42

使用
copy[i][1]
在内部调用
copy\u array()
之前创建临时数组,然后在进入
copy\u array()
时将其删除,以避免后续代码假设
copy[i]中存在的内容
是标量-这与在使用
split()
之前必须创建临时数组的方式相同(它首先在内部删除作为参数传递的数组)要填充子阵列,因为默认情况下假定数组元素的内容为标量,以便与为不支持数组数组(例如POSIX AWK)的AWK编写的代码向后兼容,请执行以下操作:

a[1] = 1
a[2][1] = 21
a[2][2] = 22
a[3] = 3
a[4][1][1] = 411
a[4][2] = 42
----------
b[1] = 1
b[2][1] = 21
b[2][2] = 22
b[3] = 3
b[4][1][1] = 411
b[4][2] = 42
$ cat tst.awk
BEGIN {
    a[1] = 1
    a[2][1] = 21
    a[2][2] = 22
    a[3] = 3
    a[4][1][1] = 411
    a[4][2] = 42

    walk_array(a, "a")

    copy_array(a, b)

    print "----------"

    walk_array(b, "b")
}

function copy_array(orig, copy,      i)
{
    delete copy         # Empty "copy" for first call and delete the temp
                        # array added by copy[i][1] below for subsequent.
    for (i in orig) {
        if (isarray(orig[i])) {
            copy[i][1]  # Force copy[i] to also be an array by creating a temp
            copy_array(orig[i], copy[i])
        }
        else {
            copy[i] = orig[i]
        }
    }
}

function walk_array(arr, name,      i)
{
    for (i in arr) {
        if (isarray(arr[i]))
            walk_array(arr[i], (name "[" i "]"))
        else
            printf("%s[%s] = %s\n", name, i, arr[i])
    }
}
$ awk -f  tst.awk
a[1] = 1
a[2][1] = 21
a[2][2] = 22
a[3] = 3
a[4][1][1] = 411
a[4][2] = 42
----------
b[1] = 1
b[2][1] = 21
b[2][2] = 22
b[3] = 3
b[4][1][1] = 411
b[4][2] = 42
$ printf 'a b\nc d\n' |
  awk '{split($0,arr[NR])} END{for (i in arr) for (j in arr[i]) print i,j,arr[i][j]}'
awk: cmd. line:1: (FILENAME=- FNR=1) fatal: split: second argument is not an array

$ printf 'a b\nc d\n' |
  awk '{arr[NR][1]; split($0,arr[NR])} END{for (i in arr) for (j in arr[i]) print i,j,arr[i][j]}'
1 1 a
1 2 b
2 1 c
2 2 d