Mengakses variabel indeks array dari loop skrip bash shell?

18

Saya ingin mengakses variabel indeks array sambil mengulang melalui array di skrip bash shell saya.

myscript.sh
#!/bin/bash
AR=('foo' 'bar' 'baz' 'bat')
for i in ${AR[*]}; do
  echo $i
done

Hasil dari skrip di atas adalah:

foo
bar
baz
bat

Hasil yang saya cari adalah:

0
1
2
3

Bagaimana cara mengubah skrip saya untuk mencapai ini?

Mowzer
sumber
7
Juga ingat bahwa Anda pada dasarnya tidak ingin "${array[*]}"bukan "${array[@]}". Menggunakan *alih-alih @kurang lebih memperlakukannya sebagai string, bukan array.
jordanm

Jawaban:

24

Anda dapat melakukan ini menggunakan Daftar kunci array . Dari bashhalaman manual:

${!name[@]}
${!name[*]}

Daftar kunci array . Jika nama adalah variabel array, perluas daftar indeks array (kunci) yang ditetapkan dalam nama. Jika nama bukan array, perluas 0jika nama diatur dan null sebaliknya. Ketika @digunakan dan ekspansi muncul dalam tanda kutip ganda, setiap kunci diperluas ke kata yang terpisah.

Sebagai contoh Anda:

#!/bin/bash
AR=('foo' 'bar' 'baz' 'bat')
for i in "${!AR[@]}"; do
  printf '${AR[%s]}=%s\n' "$i" "${AR[i]}"
done

Ini menghasilkan:

${AR[0]}=foo
${AR[1]}=bar
${AR[2]}=baz
${AR[3]}=bat

Perhatikan bahwa ini juga berfungsi untuk indeks yang tidak berurutan:

#!/bin/bash
AR=([3]='foo' [5]='bar' [25]='baz' [7]='bat')
for i in "${!AR[@]}"; do
  printf '${AR[%s]}=%s\n' "$i" "${AR[i]}"
done

Ini menghasilkan:

${AR[3]}=foo
${AR[5]}=bar
${AR[7]}=bat
${AR[25]}=baz
jordanm
sumber
1
Meskipun jawaban ini mencapai hasil yang diinginkan, itu tidak perlu dikaburkan oleh pernyataan printf. Misalnya: printf "$i=(${AR[i]})\n"atau echo "$i=(${ARi]})"keduanya memberikan sedikit tambahan dengan menunjukkan cara mendapatkan kunci & var tetapi secara tegas echo "$i"akan menjawab OP. Sisanya adalah "bash fu" :)
dimmech
6

Tambahan untuk jawaban jordanm Anda juga dapat melakukan Cloop seperti di bash:

for ((idx=0; idx<${#array[@]}; ++idx)); do
    echo "$idx" "${array[idx]}"
done
pnuesel
sumber
1

Anda dapat melakukan sesuatu seperti ini:

#!/bin/bash
AR=('foo' 'bar' 'baz' 'bat')
length=${#AR[@]}
for (( i = 0; i < length; i++ )); do
  echo "$i"
done

keluaran:

0
1
2
3
F.9876
sumber
1
Apa yang  dikatakan oleh jawaban pfnuesel ini   ?
G-Man Mengatakan 'Reinstate Monica'
Saya mungkin salah tetapi apakah pfnuesels menjawab tidak mengevaluasi ulang panjang array pada setiap iterasi?
Chris