awk를 사용하여 배열 내용을 인쇄할 때 잘못된 출력이 나오는 이유는 무엇입니까?

awk를 사용하여 배열 내용을 인쇄할 때 잘못된 출력이 나오는 이유는 무엇입니까?

awk파일에서 행렬을 읽고 bash 스크립트에 선언된 행렬에 할당하려고 합니다. 그러나 모든 것이 올바른지 확인하기 위해 행렬의 내용을 인쇄하려고 하면 이상한 결과 가 나옵니다. 함수가 내 행렬을 덮어쓰고 있습니다. 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가 적절한 2D 배열을 지원하지 않는다고 생각합니다. 보자:

$ 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

관련 정보