Array multidimensi di Bash

Saya sedang merencanakan skrip untuk mengelola beberapa bagian sistem Linux saya dan saya sedang memutuskan apakah saya ingin menggunakan bash atau ular piton.

Saya lebih suka melakukan ini sebagai skrip Bash hanya karena perintahnya lebih mudah, tetapi faktor penentu sebenarnya adalah konfigurasi. Saya harus dapat menyimpan array multidimensi dalam file konfigurasi untuk memberi tahu skrip apa yang harus dilakukan dengan array itu sendiri. Menyimpan pasangan kunci=nilai sederhana dalam file konfigurasi cukup mudah dengan bash, tetapi satu-satunya cara yang dapat saya pikirkan untuk melakukan array multidimensi adalah mesin parsing dua lapisan, seperti

array=&d1|v1;v2;v3&d2|v1;v2;v3

tetapi kode marshall/unmarshall bisa menjadi sangat buruk dan jauh dari ramah pengguna untuk orang-orang malang berikutnya yang harus mengelola ini. Jika saya tidak dapat melakukan ini dengan mudah di bash saya cukup menulis konfigurasi ke file xml dan menulis skrip dengan python.

Apakah ada cara mudah untuk melakukan ini di bash?

terimakasih semuanya.


person scphantm    schedule 27.06.2012    source sumber
comment
Terkait: Cara mendeklarasikan array 2D di bash   -  person kenorb    schedule 29.09.2015


Jawaban (13)


Bash tidak mendukung array multidimensi, atau hash, dan tampaknya Anda menginginkan hash yang nilainya berupa array. Solusi ini tidak terlalu bagus, solusi dengan file xml seharusnya lebih baik:

array=('d1=(v1 v2 v3)' 'd2=(v1 v2 v3)')
for elt in "${array[@]}";do eval $elt;done
echo "d1 ${#d1[@]} ${d1[@]}"
echo "d2 ${#d2[@]} ${d2[@]}"

EDIT: jawaban ini cukup lama, karena bash 4 mendukung tabel hash, lihat juga jawaban ini untuk solusi tanpa eval.

person Nahuel Fouilleul    schedule 27.06.2012
comment
Itulah jawaban yang kuharapkan, tapi tidak pernah hati untuk bertanya. Terima kasih - person scphantm; 28.06.2012
comment
Hanya sebuah catatan. bash mendukung hash (array asosiatif) mulai dari versi 4. info lebih lanjut: mywiki.wooledge.org/BashFAQ/ 006 - person poncha; 21.04.2013
comment
Sekadar informasi, array asosiatif dapat memiliki beberapa atribut 'deklarasikan' yang disetel di dalamnya, seperti 'disetel ke huruf besar saat penugasan' namun, array tersebut tidak dapat disetel ke array -A [asosiatif] atau -a [numerik], maupun - n kumpulan referensi, tetapi Anda BISA menandai nama variabel Anda dengan nomor, dan menggunakan variabel di tempatnya: MYARR_$i_[$j] akan menjadi yang paling mendekati ini, namun ini bukan array md yang sebenarnya, tapi ini yang terbaik kamu akan mendapatkan. Anda juga dapat menggunakan fungsi sebagai sistem pseudo-array jika Anda cukup putus asa :) - person osirisgothra; 02.05.2014
comment
dan itu dia... jahat... maaf maksudku eval - person Angry 84; 31.12.2015
comment
Anda selalu bisa declare -a "$elt" daripada eval $elt. - person ghoti; 20.07.2017
comment
@ghoti, ya jawabannya cukup lama, jawaban serupa lainnya stackoverflow.com/a/44831174/1454708, saya kira begitu OP tahu apa yang dia lakukan dan masukan diperiksa - person Nahuel Fouilleul; 20.07.2017

Bash tidak memiliki array multidimensi. Tapi Anda bisa mensimulasikan efek yang agak mirip dengan array asosiatif. Berikut ini contoh array asosiatif yang berpura-pura digunakan sebagai array multidimensi:

declare -A arr
arr[0,0]=0
arr[0,1]=1
arr[1,0]=2
arr[1,1]=3
echo "${arr[0,0]} ${arr[0,1]}" # will print 0 1

Jika Anda tidak mendeklarasikan array sebagai asosiatif (dengan -A), cara di atas tidak akan berfungsi. Misalnya, jika Anda menghilangkan baris declare -A arr, maka echo akan mencetak 2 3 dan bukan 0 1, karena 0,0, 1,0 dan sebagainya akan dianggap sebagai ekspresi aritmatika dan dievaluasi menjadi 0 (nilai di sebelah kanan operator koma).

person Jahid    schedule 17.07.2015
comment
menyatakan -A [arrayname] memunculkan opsi yang tidak valid, setidaknya di OS X. - person ktappe; 14.10.2016
comment
EDIT: Tampaknya OS X hadir dengan bash 3 dan opsi ini memerlukan bash 4. Terima kasih, Apple. - person ktappe; 14.10.2016

Ini berhasil berkat 1. ekspansi tidak langsung dengan ! yang menambahkan satu lapisan tipuan, dan 2. perluasan substring yang berperilaku berbeda dengan array dan dapat digunakan untuk mengirisnya seperti yang dijelaskan https://stackoverflow.com/a/1336245/317623

# Define each array and then add it to the main one
SUB_0=("name0" "value 0")
SUB_1=("name1" "value;1")
MAIN_ARRAY=(
  SUB_0[@]
  SUB_1[@]
)

# Loop and print it.  Using offset and length to extract values
COUNT=${#MAIN_ARRAY[@]}
for ((i=0; i<$COUNT; i++))
do
  NAME=${!MAIN_ARRAY[i]:0:1}
  VALUE=${!MAIN_ARRAY[i]:1:1}
  echo "NAME ${NAME}"
  echo "VALUE ${VALUE}"
done

Ini didasarkan pada jawaban ini di sini

person Paul Sheldrake    schedule 03.02.2015
comment
seharusnya NAME=${!MAIN_ARRAY[i]:0:1} dan VALUE=${!MAIN_ARRAY[i]:1:1} kalau tidak salah ini berfungsi (mis. Tukar URLS dengan MAIN). - person Christian; 27.10.2015
comment
Saya belum mengetahui alasannya - tetapi ini berfungsi dengan baik di bash v4.3+ tetapi memiliki masalah dengan versi sebelumnya. (mencetak karakter individual, bukan kata lengkap) - person dtmland; 17.05.2019
comment
Saya berharap dengan akan bekerja tanpa harus mendefinisikan SUB_0 dan SUB_1 sebelum MAIN_ARRAY - person freethebees; 12.11.2019
comment
@dtmland apa yang tampaknya terjadi dengan versi bash yang lebih lama adalah ekspansi substring biasa alih-alih alternatif pemotongan array. - person MarcH; 02.07.2020

Terlepas dari shell yang digunakan (sh, ksh, bash, ...) pendekatan berikut bekerja cukup baik untuk array n-dimensi (sampel mencakup array 2 dimensi).

Dalam sampel pemisah garis (dimensi ke-1) adalah karakter spasi. Untuk memperkenalkan pemisah bidang (dimensi ke-2) alat unix standar tr digunakan. Pemisah tambahan untuk dimensi tambahan dapat digunakan dengan cara yang sama.

Tentu saja kinerja pendekatan ini tidak terlalu baik, namun jika kinerja bukan merupakan kriteria, pendekatan ini cukup umum dan dapat memecahkan banyak masalah:

array2d="1.1:1.2:1.3 2.1:2.2 3.1:3.2:3.3:3.4"

function process2ndDimension {
    for dimension2 in $*
    do
        echo -n $dimension2 "   "
    done
    echo
}

function process1stDimension {
    for dimension1 in $array2d
    do
        process2ndDimension `echo $dimension1 | tr : " "`
    done
}

process1stDimension

Output dari sampel tersebut terlihat seperti ini:

1.1     1.2     1.3     
2.1     2.2     
3.1     3.2     3.3     3.4 
person yaccob    schedule 05.10.2013
comment
Namun, tidak berfungsi dengan baik jika nilainya mengandung spasi atau titik dua. :) - person dannysauer; 01.06.2016
comment
@dannysauer - akan baik-baik saja jika Anda menyandikan spasi dan titik dua sebagai entitas atau kode hex. %20 dan %3a misalnya. Seharusnya cukup mudah untuk memproses input dan output dari array melalui fungsi-fungsi tersebut jika itu menjadi perhatian Anda. - person ghoti; 13.09.2016
comment
Jadi nilainya tidak mengandung spasi atau titik dua. :D - person dannysauer; 13.09.2016
comment
Bisakah saya memiliki satu loop dan satu fungsi, bukan dua? - person Timo; 07.06.2021

Jika Anda ingin menggunakan skrip bash dan tetap mudah dibaca, rekomendasikan untuk meletakkan data dalam JSON terstruktur, lalu gunakan ringan alat jq dalam perintah bash Anda untuk mengulangi array. Misalnya dengan dataset berikut:

[

    {"specialId":"123",
    "specialName":"First"},

    {"specialId":"456",
    "specialName":"Second"},

    {"specialId":"789",
    "specialName":"Third"}
]

Anda dapat mengulangi data ini dengan skrip bash dan jq seperti ini:

function loopOverArray(){

    jq -c '.[]' testing.json | while read i; do
        # Do stuff here
        echo "$i"
    done
}

loopOverArray

Keluaran:

{"specialId":"123","specialName":"First"}
{"specialId":"456","specialName":"Second"}
{"specialId":"789","specialName":"Third"}
person Dustin    schedule 15.06.2019
comment
Terima kasih untuk ini. Jelas merupakan solusi pragmatis yang paling mudah. Kita bisa menyerahkan kemurnian kepada orang-orang yang murni. - person Martin Bramwell; 17.07.2020

Setelah banyak percobaan dan kesalahan saya benar-benar menemukan array multidimensi terbaik, paling jelas dan termudah di bash adalah dengan menggunakan var biasa. Ya.

Keuntungan: Anda tidak perlu mengulang array yang besar, Anda cukup echo "$var" dan menggunakan grep/awk/sed. Mudah dan jelas dan Anda dapat memiliki kolom sebanyak yang Anda suka.

Contoh:

$ var=$(echo -e 'kris hansen oslo\nthomas jonson peru\nbibi abu johnsonville\njohnny lipp peru')

$ echo "$var"
kris hansen oslo
thomas johnson peru
bibi abu johnsonville
johnny lipp peru

Jika Anda ingin menemukan semua orang di peru

$ echo "$var" | grep peru
thomas johnson peru
johnny lipp peru

Hanya grep(sed) di bidang ketiga

$ echo "$var" | sed -n -E '/(.+) (.+) peru/p'
thomas johnson peru
johnny lipp peru

Jika Anda hanya ingin bidang x

$ echo "$var" | awk '{print $2}'
hansen
johnson
abu
johnny

Semua orang di Peru memanggil Thomas dan mengembalikan nama belakangnya

$ echo "$var" |grep peru|grep thomas|awk '{print $2}'
johnson

Pertanyaan apa pun yang dapat Anda pikirkan... sangat mudah.

Untuk mengubah item:

$ var=$(echo "$var"|sed "s/thomas/pete/")

Untuk menghapus baris yang berisi "x"

$ var=$(echo "$var"|sed "/thomas/d")

Untuk mengubah bidang lain di baris yang sama berdasarkan nilai dari item lain

$ var=$(echo "$var"|sed -E "s/(thomas) (.+) (.+)/\1 test \3/")
$ echo "$var"
kris hansen oslo                                                                                                                                             
thomas test peru                                                                                                                                          
bibi abu johnsonville
johnny lipp peru

Tentu saja perulangan juga berfungsi jika Anda ingin melakukannya

$ for i in "$var"; do echo "$i"; done
kris hansen oslo
thomas jonson peru
bibi abu johnsonville
johnny lipp peru

Satu-satunya hal yang saya temukan dengan ini adalah Anda harus selalu mengutip var (dalam contoh; var dan i) atau semuanya akan terlihat seperti ini

$ for i in "$var"; do echo $i; done
kris hansen oslo thomas jonson peru bibi abu johnsonville johnny lipp peru

dan seseorang pasti akan mengatakan itu tidak akan berfungsi jika Anda memiliki spasi di masukan Anda, namun hal itu dapat diperbaiki dengan menggunakan pembatas lain di masukan Anda, misalnya (menggunakan karakter utf8 sekarang untuk menekankan bahwa Anda dapat memilih sesuatu yang tidak akan dipilih oleh masukan Anda berisi, tetapi Anda dapat memilih apa saja):

$ var=$(echo -e 'field one☥field two hello☥field three yes moin\nfield 1☥field 2☥field 3 dsdds aq')

$ for i in "$var"; do echo "$i"; done
field one☥field two hello☥field three yes moin
field 1☥field 2☥field 3 dsdds aq

$ echo "$var" | awk -F '☥' '{print $3}'
field three yes moin
field 3 dsdds aq

$ var=$(echo "$var"|sed -E "s/(field one)☥(.+)☥(.+)/\1☥test☥\3/")
$ echo "$var"
field one☥test☥field three yes moin
field 1☥field 2☥field 3 dsdds aq

Jika Anda ingin menyimpan baris baru di masukan Anda, Anda dapat mengonversi baris baru menjadi baris lain sebelum masukan dan mengonversinya kembali pada keluaran (atau jangan gunakan bash...). Menikmati!

person n00p    schedule 25.04.2017
comment
Ini mungkin berfungsi untuk dua dimensi, tetapi untuk kasus umum dengan n dimensi, hal ini semakin sulit. - person U. Windl; 16.11.2017
comment
Itu benar. Ketika saya menulis ini saya tidak menyadari perbedaan antara 2d, 3d, 4d dan yang saya perlukan hanyalah dukungan tabel/db yang baik. Sekarang, saya masih belum memerlukan apa pun selain 2d, tetapi jika ada yang membutuhkan lebih maka saya kira ini tidak akan berhasil. - person n00p; 17.11.2017

Memperluas jawaban Paul - inilah versi saya bekerja dengan sub-array asosiatif di bash:

declare -A SUB_1=(["name1key"]="name1val" ["name2key"]="name2val")
declare -A SUB_2=(["name3key"]="name3val" ["name4key"]="name4val")
STRING_1="string1val"
STRING_2="string2val"
MAIN_ARRAY=(
  "${SUB_1[*]}"
  "${SUB_2[*]}"
  "${STRING_1}"
  "${STRING_2}"
)
echo "COUNT: " ${#MAIN_ARRAY[@]}
for key in ${!MAIN_ARRAY[@]}; do
    IFS=' ' read -a val <<< ${MAIN_ARRAY[$key]}
    echo "VALUE: " ${val[@]}
    if [[ ${#val[@]} -gt 1 ]]; then
        for subkey in ${!val[@]}; do
            subval=${val[$subkey]}
            echo "SUBVALUE: " ${subval}
        done
    fi
done

Ia bekerja dengan nilai campuran di array utama - string/array/assoc. array

Kuncinya di sini adalah untuk membungkus subarray dalam tanda kutip tunggal dan menggunakan * sebagai pengganti @ ketika menyimpan subarray di dalam array utama sehingga akan disimpan sebagai string tunggal yang dipisahkan spasi: "${SUB_1[*]}"

Kemudian memudahkan untuk mengurai array darinya ketika mengulang nilai dengan IFS=' ' read -a val <<< ${MAIN_ARRAY[$key]}

Kode di atas menghasilkan:

COUNT:  4
VALUE:  name1val name2val
SUBVALUE:  name1val
SUBVALUE:  name2val
VALUE:  name4val name3val
SUBVALUE:  name4val
SUBVALUE:  name3val
VALUE:  string1val
VALUE:  string2val
person Vigintas Labakojis    schedule 12.02.2015
comment
Jadi Anda tidak bisa menyimpan string yang mengandung spasi (tidak menyebutkan baris baru). Kurangnya tanda kutip juga membuat tidak mungkin memiliki karakter glob dengan aman. - person gniourf_gniourf; 12.02.2015
comment
Ya, saya baru menyadari itu akan memecah string dengan spasi menjadi sub-nilai yang terpisah, tapi saya pribadi bisa menerimanya jika itu hanya nilai konfigurasi... Tapi saya pikir itu adalah hal terbaik yang bisa kita lakukan di bash. Saya terbuka untuk saran/perbaikan. Menambahkan tanda kutip, terima kasih sudah menunjukkan :) - person Vigintas Labakojis; 12.02.2015
comment
Hai, bisakah Anda menjelaskan cara kerja IFS=' ' read -a val <<< ${MAIN_ARRAY[$key]}. Apa itu IFS? Apakah itu variabel yang didefinisikan di sana? Mengapa read ditambahkan ke definisi variabel? - person Boyang; 09.02.2016
comment
@CharlesW. Lihat Panduan Referensi Bash, 5.1 Variabel Bourne Shell: IFS – Daftar karakter yang memisahkan bidang; digunakan ketika shell membagi kata-kata sebagai bagian dari ekspansi. dan 6.7 Array: Jika kata diberi tanda kutip ganda, ${name[*]} diperluas menjadi satu kata dengan nilai setiap anggota array dipisahkan oleh karakter pertama variabel IFS, .... - person Gerold Broser; 08.06.2016

Banyak jawaban ditemukan di sini untuk membuat array multidimensi di bash.

Dan tanpa kecuali, semuanya tumpul dan sulit digunakan.

Jika susunan MD merupakan kriteria yang diperlukan, sekarang saatnya mengambil keputusan:

Gunakan bahasa yang mendukung array MD

Preferensi saya adalah Perl. Sebagian besar mungkin akan memilih Python. Keduanya berhasil.

Simpan data di tempat lain

JSON dan jq sudah disarankan. XML juga telah disarankan, meskipun untuk penggunaan Anda JSON dan jq mungkin akan lebih sederhana.

Tampaknya Bash mungkin bukan pilihan terbaik untuk apa yang perlu Anda lakukan.

Kadang-kadang pertanyaan yang tepat bukanlah "Bagaimana saya melakukan X pada alat Y?", melainkan "Alat manakah yang terbaik untuk melakukan X?"

person Jared Still    schedule 03.09.2019

Saya memposting yang berikut ini karena ini adalah cara yang sangat sederhana dan jelas untuk meniru (setidaknya sampai batas tertentu) perilaku array dua dimensi di Bash. Ia menggunakan file di sini (lihat manual Bash) dan read (perintah bawaan Bash):

## Store the "two-dimensional data" in a file ($$ is just the process ID of the shell, to make sure the filename is unique)
cat > physicists.$$ <<EOF
Wolfgang Pauli 1900
Werner Heisenberg 1901
Albert Einstein 1879
Niels Bohr 1885
EOF
nbPhysicists=$(wc -l physicists.$$ | cut -sf 1 -d ' ')     # Number of lines of the here-file specifying the physicists.

## Extract the needed data
declare -a person     # Create an indexed array (necessary for the read command).                                                                                 
while read -ra person; do
    firstName=${person[0]}
    familyName=${person[1]}
    birthYear=${person[2]}
    echo "Physicist ${firstName} ${familyName} was born in ${birthYear}"
    # Do whatever you need with data
done < physicists.$$

## Remove the temporary file
rm physicists.$$

Keluaran: Physicist Wolfgang Pauli was born in 1900 Physicist Werner Heisenberg was born in 1901 Physicist Albert Einstein was born in 1879 Physicist Niels Bohr was born in 1885

Cara kerjanya:

  • Garis-garis dalam file sementara yang dibuat memainkan peran vektor satu dimensi, di mana spasi kosong (atau karakter pemisahan apa pun yang Anda pilih; lihat deskripsi perintah read di manual Bash) memisahkan elemen-elemen vektor ini.
  • Kemudian, dengan menggunakan perintah read dengan opsi -a, kita mengulang setiap baris file (sampai kita mencapai akhir file). Untuk setiap baris, kita dapat menetapkan bidang yang diinginkan (= kata) ke array, yang kita deklarasikan tepat sebelum perulangan. Opsi -r pada perintah read mencegah garis miring terbalik bertindak sebagai karakter escape, jika kita mengetikkan garis miring terbalik di dokumen ini physicists.$$.

Kesimpulannya, sebuah file dibuat sebagai array 2D, dan elemen-elemennya diekstraksi menggunakan loop pada setiap baris, dan menggunakan kemampuan perintah read untuk menetapkan kata-kata ke elemen array (yang diindeks).

Sedikit peningkatan:

Pada kode di atas, file physicists.$$ diberikan sebagai masukan ke loop while, sehingga sebenarnya diteruskan ke perintah read. Namun, saya menemukan bahwa ini menyebabkan masalah ketika saya memiliki perintah lain yang meminta masukan di dalam loop while. Misalnya, perintah select menunggu masukan standar, dan jika ditempatkan di dalam perulangan while, perintah tersebut akan mengambil masukan dari physicists.$$, alih-alih meminta masukan pengguna di baris perintah. Untuk memperbaikinya, saya menggunakan opsi -u dari read, yang memungkinkan untuk membaca dari deskriptor file. Kita hanya perlu membuat deskriptor file (dengan perintah exec) yang sesuai dengan physicists.$$ dan memberikannya ke opsi baca -u, seperti pada kode berikut:

## Store the "two-dimensional data" in a file ($$ is just the process ID of the shell, to make sure the filename is unique)
cat > physicists.$$ <<EOF
Wolfgang Pauli 1900
Werner Heisenberg 1901
Albert Einstein 1879
Niels Bohr 1885
EOF
nbPhysicists=$(wc -l physicists.$$ | cut -sf 1 -d ' ')     # Number of lines of the here-file specifying the physicists.
exec {id_file}<./physicists.$$     # Create a file descriptor stored in 'id_file'.

## Extract the needed data
declare -a person     # Create an indexed array (necessary for the read command).                                                                                 
while read -ra person -u "${id_file}"; do
firstName=${person[0]}
familyName=${person[1]}
birthYear=${person[2]}
echo "Physicist ${firstName} ${familyName} was born in ${birthYear}"
# Do whatever you need with data
done

## Close the file descriptor
exec {id_file}<&-
## Remove the temporary file
rm physicists.$$

Perhatikan bahwa deskriptor file ditutup di bagian akhir.

person Giuseppe    schedule 27.09.2017
comment
Ini hampir sama dengan solusi user7909577. Namun yang Anda lakukan adalah menulis rangkaian baris dalam file teks. Jadi dimensi 1 adalah nomor garis. Dimensi 2 adalah kata dalam satu baris. Namun, solusi yang benar-benar umum akan memungkinkan untuk menempatkan array apa pun di array mana pun. Dan itu tidak akan berhasil. Oke, Anda bisa menerapkan dimensi dengan membuat indentasi garis, tapi itu masih kurang elegan. - person U. Windl; 16.11.2017
comment
@U. Windi meletakkan array apa pun di array mana pun. Dan itu tidak akan berhasil.: Itu sebabnya saya menekankan dalam jawaban saya bahwa itu adalah untuk mensimulasikan 2D-ARRAYS. Ini sangat mirip dengan solusi pengguna7909577: Saya rasa tidak, dia mem-parsing string dengan sed/grep/awk dalam jawabannya, dan saya melakukannya dengan mengubah string menjadi array terlebih dahulu, kemudian menggunakan indeks (itu itulah sebabnya ia mensimulasikan perilaku array). - person Giuseppe; 16.11.2017
comment
@Guiseppe: Namun kedua solusi menggunakan file teks sebagai representasi untuk array dua dimensi dengan dimensi seperti yang telah saya jelaskan. Pertanyaan khususnya adalah tentang array multi dimensi (Ada pertanyaan terpisah untuk array dua dimensi). - person U. Windl; 16.11.2017
comment
@U. Windl: Saya setuju, tetapi ketika saya memahami solusi pengguna7909577, itu sebenarnya bukan array yang Anda miliki, tetapi daftar panjang di mana Anda harus meletakkan pemisah (seperti baris baru). Jadi setiap kali Anda memulai perulangan baru, Anda terjebak dengan satu elemen dari daftar panjang Anda. Sebaliknya dengan solusi saya, di setiap loop Anda bekerja dengan array 1D nyata (garis array 2D yang disimulasikan), dan karena itu Anda dapat mengakses salah satu elemennya, yang menurut saya jauh lebih nyaman. Saya tidak memperhatikan pertanyaan lain tentang array dua dimensi, jadi jika Anda tahu cara memindahkan jawaban, saya tertarik. - person Giuseppe; 16.11.2017

Saya melakukan ini menggunakan array asosiatif sejak bash 4 dan menyetel IFS ke nilai yang dapat ditentukan secara manual.

Tujuan dari pendekatan ini adalah untuk menjadikan array sebagai nilai kunci array asosiatif.

Untuk mengembalikan IFS ke default, hapus saja.

  • unset IFS

Ini adalah contohnya:

#!/bin/bash

set -euo pipefail

# used as value in asscciative array
test=(
  "x3:x4:x5"
)
# associative array
declare -A wow=(
  ["1"]=$test
  ["2"]=$test
)
echo "default IFS"
for w in ${wow[@]}; do
  echo "  $w"
done

IFS=:
echo "IFS=:"
for w in ${wow[@]}; do
  for t in $w; do
    echo "  $t"
  done
done
echo -e "\n or\n"
for w in ${!wow[@]}
do
  echo "  $w"
  for t in ${wow[$w]}
  do
    echo "    $t"
  done
done

unset IFS
unset w
unset t
unset wow
unset test

Output dari skrip di bawah ini adalah:

default IFS
  x3:x4:x5
  x3:x4:x5
IFS=:
  x3
  x4
  x5
  x3
  x4
  x5

 or

  1
    x3
    x4
    x5
  2
    x3
    x4
    x5
person rocksteady    schedule 30.06.2017
comment
Saya tidak melihat alasan untuk menggunakan test=("x3:x4:x5") ketika Anda mereferensikannya sebagai $test: Anda cukup melakukan test="x3:x4:x5" . - person U. Windl; 16.11.2017
comment
Ya, Anda benar sekali. Terima kasih atas petunjuknya. - person rocksteady; 18.11.2017

Bash tidak mendukung array multidimensi, tetapi kita dapat mengimplementasikannya menggunakan array Associate. Di sini indeks adalah kunci untuk mengambil nilainya. Array asosiasi tersedia dalam bash versi 4.

#!/bin/bash

declare -A arr2d
rows=3
columns=2

for ((i=0;i<rows;i++)) do
    for ((j=0;j<columns;j++)) do
        arr2d[$i,$j]=$i
    done
done


for ((i=0;i<rows;i++)) do
    for ((j=0;j<columns;j++)) do
        echo ${arr2d[$i,$j]}
    done
done
person rashok    schedule 23.04.2018

Saya punya solusi yang cukup sederhana namun cerdas: Cukup tentukan array dengan variabel di namanya. Misalnya:

for (( i=0 ; i<$(($maxvalue + 1)) ; i++ ))
  do
  for (( j=0 ; j<$(($maxargument + 1)) ; j++ ))
    do
    declare -a array$i[$j]=((Your rule))
  done
done

Tidak tahu apakah ini membantu karena ini bukan yang Anda minta, tetapi ini berhasil untuk saya. (Hal yang sama dapat dicapai hanya dengan variabel tanpa array)

person testiner    schedule 18.01.2018

person    schedule
comment
Ingin menambahkan beberapa kata penjelasan tentang apa yang seharusnya dilakukan kode tersebut? Meskipun beberapa pemformatan juga membantu, beberapa komentar akan lebih meningkatkan jawabannya. Meskipun saya dapat melihat banyak array, saya tidak melihat array multidimensi di sini. - person Izzy; 06.11.2014