如何使用 awk 从文件中读取矩阵并分配给 bash 脚本中声明的二维数组(矩阵)

如何使用 awk 从文件中读取矩阵并分配给 bash 脚本中声明的二维数组(矩阵)

echo当我矩阵的元素时,我在打印时遇到问题,当我在第一个循环中取消注释时echo ${matrix[$i,$j]},程序工作正常,但是当我想${matrix[$i,$j]}在第二个循环中打印时,输出为空字符。目标是从文件中读取矩阵并分配给我的矩阵在脚本中声明的矩阵。

function readMatrixFromFile() {
        local file="$1"
        declare -A matrix
        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
                        k=i-2
                        matrix[$k,$j]=$(awk -v row=$i -v col=$j 'NR==row {print $col}' $file)
                        #echo ${matrix[$i,$j]}
                done
        done


        for ((i=1;i<=num_rows;i++)) do
               for ((j=1;j<=num_colums;j++)) do
                       echo ${matrix[$i,$j]}
               done
               echo
        done

}

function Main() {
        readMatrixFromFile Matrix3.txt
}

Main

这是Matrix3.txt

在此输入图像描述

这是输出:

在此输入图像描述

答案1

#!/bin/bash                                                                                                           

declare -A m

read_matrix() {
    local i=0
    local line
    local j
    # Ignore the first 2 lines containing size of the matrix
    read rows
    read cols
    while read -r line; do
        j=0
        # split on spaces
        for v in `echo $line`; do
            m[$i,$j]="$v"
            j=$((j+1))
        done
        i=$((i+1))
    done
}

read_matrix < matrix.file

echo ${m[1,2]}

答案2

我相信,这看起来是局部变量作用域与全局变量作用域问题。

我在尝试提取数据时发现了一个类似的“空”数组 - 但确定函数内部声明的数组的内容只能在函数内检索,因为我在那里定义了(原始帖子显示了这正是我的情况)

注意:您可以在脚本的 MAIN 部分之前放置一个函数,这不会成为问题,因为它的使用与进一步向下的函数调用相关联

将数据表加载到二维数组中,以便它可以在 BASH 脚本的主要部分的循环内变得可操作 - 下面的内容在上面的内容之前执行,因为上面的内容完全包含在函数定义范围内

#!/bin/bash

echo "Let's first define the function before the Main Body of Script"

function DEFINESCOPE {

    for ((Row=1;Row<=num_rows;Row++)) 
    do

      for ((Col=1;Col<=num_columns;Col++)) 
      do

        RowData=`cat $STATSFile | head -${Row} | tail -1 | awk -v c1=$Col -F\, '{print $c1}' | sed -e 's/"//g'`

        matrix[$Row,$Col]=$RowData

        echo "Checking to see if the loaded data can be pulled: Matrix[$Row,$Col] = ${matrix[$Row,$Col]}"

     done

   done
} 

echo "End of Function DEFINESCOPE"

echo "Start of MAIN part of script"

STATSFile="STATSFile"
cat $STATSFile
declare -A matrix

echo "THIS IS THE FUNCTION CALL WHERE THE DATA IS LOADED per the above code"

DEFINESCOPE

echo "NOW TO PULL THE DATA WHILE IN THE MAIN PART OF THE SCRIPT"

echo "In this case I want to start by skipping over the first 3 columns and then walk the rows for each column"

StartRow="1"
StartCol="4"
Row=$StartRow
Col=$StartCol

for ((Col=${StartCol};Col<=num_columns;Col++)) 
do
    Row=$StartRow
    echo "Current Position: Matrix[$Row,$Col] = ${matrix[${Row},${Col}]}"
    ReportType=${matrix[$Row,$Col]}

    echo "============================================="
    echo "Walking NEW Report Type: $ReportType"
    for ((Row=${StartRow};Row<=num_rows;Row++)) 
    do

        echo "Using a CASE statement instead of a bunch of if.then.else.fi..."
        echo "Pull Metric Data for C/H/M/L Severity Row Counts"
        echo "Determine which type of row we're examining and then assign values"

         case "${matrix[$Row,1]}" in
             Critical)
                 Criticals=${matrix[$Row,$Col]}
                 echo "Setting Severity Count for Criticals: $Criticals"
                 ;;
             Highs)
                 Highs=${matrix[$Row,$Col]}
                 echo "Setting Severity Count for Highs: $Highs"
                 ;;
             Mediums)
                 Mediums=${matrix[$Row,$Col]}
                 echo "Setting Severity Count for Mediums: $Mediums"
                 ;;
             Lows)
                 Lows=${matrix[$Row,$Col]}
                 echo "Setting Severity Count for Lows: $Lows"
                 ;;
             *)
                 echo "Case *): Does not match: matrix[Row,1]: ${matrix[$Row,1]}"
                 ;;
         esac
         echo "Current Data Position: matrix[Row,Col]: ${matrix[$Row,$Col]}"
         echo "Current Row Position: matrix[Row,1]: ${matrix[$Row,1]}"
     done
done

echo "Thus, I moved the 'declare' statement to the main part of the bash"
echo "script, prior to the function call, loaded the data in the function," echo "and then I was then able to pull data from the array when in the main part of the script."

echo "Bottom Line: declare your array in the main part of the script, before you call a function/subroutine to load or output array data."

相关内容