【问题标题】:How do you copy a multi-dimensional array (i.e. an array of arrays) in awk?如何在 awk 中复制多维数组(即数组的数组)?
【发布时间】:2020-09-22 13:25:33
【问题描述】:

这个问题的目的是用非显而易见的解决方案发布一个规范的答案 - 复制数组数组(需要 GNU awk 用于数组数组)。

给定一个数组,如 gawk 手册中关于 traversing arrays 部分所示:

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")
}

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])
    }
}

您将如何编写一个 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

【问题讨论】:

    标签: awk


    【解决方案1】:
    $ 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
    

    使用copy[i][1] 在内部调用copy_array() 之前创建一个临时数组,然后在进入copy_array() 时将其删除是为了避免后续代码假设copy[i] 存在的内容是一个标量- 这与在使用split()(在内部首先删除您作为参数传递的数组)填充子数组之前必须创建临时数组的方式相同,因为数组元素的内容被假定为标量默认为向后兼容为不支持数组的 awk 编写的代码(例如 POSIX awks):

    $ 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
    

    【讨论】:

      猜你喜欢
      • 2019-07-29
      • 1970-01-01
      • 2011-03-04
      • 2014-12-25
      • 1970-01-01
      • 2015-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多