为什么当我使用 awk 打印数组内容时,它会给出错误的输出

为什么当我使用 awk 打印数组内容时,它会给出错误的输出

我试图从文件中读取矩阵并分配给在 bash 脚本中声明的矩阵,但是当我尝试打印矩阵的内容以检查一切是否正确时,它给了我一个奇怪的输出,似乎awk函数重写我的矩阵,有什么要说的awk要附加到我的矩阵而不是重写吗?

这是.txt文件。

在此输入图像描述

代码:

#!/bin/bash
function readMatrixFromFile() {
    local file="$1"
    declare -n matrix="$2"
    local num_rows=$(awk 'NR==1 {print $3}' $1)
    local num_colums=$(awk 'NR==2 {print $3}' $1)

    for ((i=3;i<=num_rows+2;i++)) do
    for ((j=1;j<=num_colums;j++)) do

        local k=$(($i-3))
        local l=$(($j-1))

                    matrix[$k,$l]=$(awk -v row=$i -v col=$j 'NR==row {print $col}' $file)       
            done
    done

    for ((i=0;i<num_rows;i++)) do
           for ((j=0;j<num_colums;j++)) do

                   echo ${matrix[$i,$j]}
           done
           echo
    done

}

function Main() {
    declare m
    readMatrixFromFile Matrix3.txt m

}

Main

这是输出:

在此输入图像描述

答案1

matrix[$k,$l]=$(...)

这个数组分配看起来很可疑。我认为 Bash 不支持正确的二维数组。让我们来看看:

$ M=()
$ M[0,0]=1
$ M[0,1]=2
$ M[1,0]=3
$ M[1,1]=4
$ declare -p M
declare -a M=([0]="3" [1]="4")

是的,数组中只存在最后一行。这实际上是因为逗号之前的任何内容都不适用,会影响算术上下文中的返回值:

$ echo $(( 123, 456 ))
456

逗号是 C 风格的逗号运算符:它计算两边并返回右边的值。左侧的任何副作用仍然会发生。它是Bash手册中提到尽管只是参考了 C 的用途。


您可能想使用关联数组相反,因为它们的键是字符串,并且逗号可以很好地适合键字符串:

$ unset M
$ declare -A M=()
$ M[0,0]=1
$ M[0,1]=2
$ M[1,0]=3
$ M[1,1]=4
$ declare -p M
declare -A M=([1,1]="4" [1,0]="3" [0,0]="1" [0,1]="2" )

您通过 nameref 使用该数组;我认为在这种情况下,你必须先将数组关联起来,然后才能使用它,所以:

function Main() {
    declare -A m
    readMatrixFromFile Matrix3.txt m
}

awk也就是说,可能有一些比启动每个元素更简单的方法来读取数组:

#!/bin/bash
set -f           # disable globbing
i=0
declare -A M=()
while IFS= read -r line; do
    j=0
    for x in $line ; do     # unquoted $line to get word-splitting!
        M[$i,$j]=$x
        j=$((j+1))
    done
    i=$((i+1))
done << EOF      # replace this with a redirection from the input file
1 2 
3 4  
EOF

declare -p M

相关内容