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

知りません。多次元配列などが必要な場合は、シェルではなく実際のプログラミング言語を使用する必要があることを意味します。シェルは実際にはプログラミング言語ではありませんが、1つとして(悪用)使用することができますが、これは単なる目的でのみ使用する必要があります。残念ながら、多くの人はシェルがあらゆる状況に適したツールだと思うようです。これにより、特定の目的のために設計されたツールを使用するのではなく、シェルができない、または非常に適切に実行できないことを試みるのに多くの労力が浪費されます。特定の状況。働く

つまり、次を使用して何かを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または...)の使用を検討する必要がある場合の1つです。シェル言語を使用すると外部プログラムを簡単に起動できますが、データ構造の操作ははるかに困難です。

答え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を使用します。

関連情報