bash를 사용하여 다차원 배열 또는 이와 유사한 것을 만드는 방법은 무엇입니까?

bash를 사용하여 다차원 배열 또는 이와 유사한 것을 만드는 방법은 무엇입니까?

Bash를 사용하여 다차원 배열을 만들어야 하는데 Bash에는 다차원 배열과 같은 것이 없다는 것을 읽었습니다.

가능한 데이터, 모양 및 필요한 데이터는 다음과 같습니다. 이것은 bash 배열이 아닙니다.

DATACOL = [
    "1"=>("Santiago","Barcelona","AWG","6792992","Male"),
    "2"=>("Santi","Texas","BGG","6792992","Male"),
    "3"=>("Tiago","Rio","GHA","6792992","Female") 
]

간단한 스크립트로 비슷한 작업을 어떻게 수행할 수 있나요? 저는 bash를 처음 접했습니다.

답변1

넌 몰라. 다차원 배열과 같은 것이 필요하다면 이는 쉘이 아닌 실제 프로그래밍 언어를 사용해야 한다는 것을 의미합니다. 쉘은 실제로 프로그래밍 언어는 아니지만 하나로 (악용) 사용될 수 있지만 이는 단순한 용도로만 사용해야 합니다. 불행하게도 많은 사람들은 셸이 모든 상황에 적합한 도구라고 생각하는 것 같습니다. 이로 인해 특정 용도로 설계된 도구를 사용하는 대신 셸이 할 수 없거나 매우 제대로 수행할 수 없는 일을 하려고 노력하는 데 많은 노력이 낭비됩니다. 특정 상황. 일하다.

즉, 다음을 사용하여 무언가를 하나로 모을 수 있습니다.이름 참조:

선언이나 로컬 내장 기능(Bash 내장 기능 참조)의 -n 옵션을 사용하여 변수에 nameref 속성을 할당하여 다른 변수에 대한 참조나 nameref를 생성할 수 있습니다. 이를 통해 변수를 간접적으로 조작할 수 있습니다. nameref 변수가 참조, 할당, 설정 해제되거나 해당 속성이 수정될 때마다(nameref 속성 자체를 사용하거나 변경하는 경우 제외) nameref 변수의 값으로 지정된 변수에 대해 작업이 실제로 수행됩니다. nameref는 일반적으로 쉘 함수에서 이름이 함수에 인수로 전달되는 변수를 참조하는 데 사용됩니다. 예를 들어 변수 이름을 셸 함수의 첫 번째 인수로 전달하는 경우 다음을 실행합니다.

declare -n ref=$1

함수 내에서 첫 번째 매개변수로 전달된 변수 이름을 값으로 갖는 nameref 변수 ref가 생성됩니다. ref에 대한 참조 및 할당과 해당 속성에 대한 변경은 이름이 $1로 전달되는 변수에 대한 참조, 할당 및 속성 수정으로 처리됩니다.

예를 들어 다음과 같습니다.

#!/bin/bash

data1=("Santiago" "Barcelona" "AWG" "6792992" "Male")
data2=("Santi" "Texas" "BGG" "6792992" "Male")
data3=("Tiago" "Rio" "GHA" "6792992" "Female")

datacol=("data1" "data2" "data3")

for arrayName in "${datacol[@]}"; do
  declare -n array="$arrayName"
  echo "The second element of the array '$arrayName' is: ${array[1]}"
done

다음을 생성합니다.

$ foo.sh
The second element of the array 'data1' is: Barcelona
The second element of the array 'data2' is: Texas
The second element of the array 'data3' is: Rio

정말 복잡하고 깨지기 쉬우며 노력할 가치가 없습니다. 대신 실제 스크립트 언어를 사용하십시오.

답변2

몇 가지 트릭 없이는 Bash에서 할 수 없습니다. 그러나 Ksh93에는 기본 다차원 배열이 있습니다.

일반적인 기술은 declare -A arr와 같은 키 1,2와 쉼표로 구분된 여러 인덱스가 있는 연관 배열( )을 사용하는 것입니다. 개별 "행"이나 "열"을 반복하는 것은 그렇게 간단하지 않습니다. 이는 AWK가 다차원 배열을 구현하는 방법이기도 합니다.GNU AWK 매뉴얼.

ksh에서:

arr=((a b c) (d e f))       # 3x2
arr[2]=(g h i)              # one more row
arr[0][2]=x                 # change a value
typeset -p arr
echo ---
for i in ${!arr[@]}; do     # ${!arr[@]} gives the indexes
   for j in ${!arr[i][@]}; do
      echo -n "${arr[i][j]} ";
   done;
   echo;
done

인쇄

typeset -a arr=((a b x) (d e f) (g h i) )
---
a b x 
d e f 
g h i 

그러나 실제로 이것은 사용 사례가 매우 구체적이지 않는 한 Python(또는 Perl 또는...) 사용을 고려해야 하는 경우 중 하나입니다. 쉘 언어를 사용하면 외부 프로그램을 쉽게 시작할 수 있지만 데이터 구조 작업은 훨씬 더 어렵습니다.

답변3

배열을 "남용"하면 원하는 효과를 얻을 수 있다는 것을 발견했습니다.

#!/bin/bash

AllServers=(
    "vmkm13, 172.16.39.71"
    "vmkm14, 172.16.39.72"
    "vmkm15, 172.16.39.84"
    "vmkw51, 172.16.39.73"
    "vmkw52, 172.16.39.74"
    "vmkw53, 172.16.39.75"
    "vmkw54, 172.16.39.76"
    "vmkw55, 172.16.39.77"
    "vmkw56, 172.16.39.78"
    "vmkw57, 172.16.39.79"
    "vmkw58, 172.16.39.80"
    "vmkw59, 172.16.39.81"
    "vmkw60, 172.16.39.82"
    "vmkw61, 172.16.39.83"
    "vmkw62, 172.16.39.85"
    "vmkw63, 172.16.39.86"
    "vmkw64, 172.16.39.87"

)

for Servers in "${AllServers[@]}"; do
    Servername=$(echo "$Servers" | awk -F',' '{ print $1 }')
    ServerIP=$(echo "$Servers" | awk -F',' '{ print $2 }')

done

이는 결코 옳지 않습니다. 그러나 데이터를 큰따옴표로 묶은 다음 항목을 쉼표로 구분하면 AWK와 같은 도구를 사용하여 열 항목을 변수로 추출할 수 있습니다. 나는 이것이 매우 해킹적인 접근 방식이라고 말했습니다. 하지만 작동합니다.

답변4

declare -p이것은 해킹적이지만 typeset -p배열을 직렬화할 수 있습니다. 이 전략을 사용하여 Bash에서 일련의 직렬화된 배열을 만든 다음 eval이를 만듭니다. 빈 문자열을 값으로 고려하려면 따옴표를 사용해야 합니다.

# multidimensional array serialized with `declare -p`
# red, yellow, green things
declare -a color_table=(
  "$(inner_row=(stop caution go);          declare -p inner_row)"
  "$(inner_row=(rose tulip clover);        declare -p inner_row)"
  "$(inner_row=(strawberry banana grape);  declare -p inner_row)"
)

이 다차원 배열을 사용하는 방법은 다음과 같습니다.

# using eval, we deserialize the inner_row variable as we loop
echo "=== table ==="
printf '%s\n' "${color_table[@]}"
echo "=== rows ==="
for row in "${color_table[@]}"; do
  eval $row
  echo "red thing: ${inner_row[0]}"
  echo "yellow thing: ${inner_row[1]}"
  echo "green thing: ${inner_row[2]}"
done

출력은 다음과 같습니다

=== table ===
declare -a inner_row=([0]="stop" [1]="caution" [2]="go")
declare -a inner_row=([0]="rose" [1]="tulip" [2]="clover")
declare -a inner_row=([0]="strawberry" [1]="banana" [2]="grape")
=== rows ===
red thing: stop
yellow thing: caution
green thing: go
red thing: rose
yellow thing: tulip
green thing: clover
red thing: strawberry
yellow thing: banana
green thing: grape

Zsh 사용자의 경우 배열이 1부터 시작하므로 이 스크립트가 작동하지만 이 예에서는 인덱싱에 0-2를 사용하는 대신 1-3을 사용합니다.

관련 정보