Truy cập biến chỉ số mảng từ vòng lặp bash shell script?


18

Tôi muốn truy cập biến chỉ mục mảng trong khi lặp thông qua một mảng trong tập lệnh shell bash của tôi.

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

Kết quả của đoạn script trên là:

foo
bar
baz
bat

Kết quả tôi tìm kiếm là:

0
1
2
3

Làm cách nào để thay đổi tập lệnh của tôi để đạt được điều này?


6
Cũng lưu ý rằng về cơ bản bạn không bao giờ muốn "${array[*]}"thay vì "${array[@]}". Sử dụng *thay vì @nhiều hơn hoặc ít hơn coi nó như một chuỗi thay vì một mảng.
jordanm

Câu trả lời:


23

Bạn có thể làm điều này bằng cách sử dụng Danh sách các phím mảng . Từ bashtrang người đàn ông:

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

Danh sách các khóa mảng . Nếu tên là một biến mảng, mở rộng ra danh sách các chỉ số mảng (khóa) được gán trong tên. Nếu tên không phải là một mảng, mở rộng thành 0nếu tên được đặt và null khác. Khi @được sử dụng và mở rộng xuất hiện trong dấu ngoặc kép, mỗi khóa sẽ mở rộng thành một từ riêng biệt.

Ví dụ của bạn:

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

Kết quả này trong:

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

Lưu ý rằng điều này cũng hoạt động cho các chỉ mục không liên tiếp:

#!/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

Kết quả này trong:

${AR[3]}=foo
${AR[5]}=bar
${AR[7]}=bat
${AR[25]}=baz

1
Mặc dù câu trả lời này hoàn thành kết quả mong muốn, nhưng nó bị che khuất một cách không cần thiết bởi câu lệnh printf. Ví dụ: printf "$i=(${AR[i]})\n"hoặc echo "$i=(${ARi]})"cả hai cung cấp thêm một chút bằng cách hiển thị cách nhận khóa & var nhưng nói đúng ra echo "$i"sẽ trả lời OP. Phần còn lại là "bash fu" :)
dimmech

6

Bổ sung cho câu trả lời của jordanm, bạn cũng có thể thực hiện một Cvòng lặp like trong bash:

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

1

bạn có thể làm một cái gì đó như thế này:

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

đầu ra:

0
1
2
3

1
Điều này nói gì mà  câu trả lời của pfnuesel   chưa nói?
G-Man nói 'Phục hồi Monica'

Tôi có thể nhầm nhưng pfnuesels trả lời không đánh giá lại độ dài mảng trên mỗi lần lặp?
Chris
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.