Доступ до змінної індексу масиву з циклу скриптів bash shell?


19

Я хочу отримати доступ до змінної індексу масиву під час циклу через масив у моєму скрипті bash shell.

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

Результатом вищезазначеного сценарію є:

foo
bar
baz
bat

Я шукаю результат:

0
1
2
3

Як я можу змінити свій сценарій, щоб досягти цього?


7
Також зауважте, що ви взагалі ніколи не хочете "${array[*]}"замість цього "${array[@]}". Використання *замість @більш-менш трактує його як рядок замість масиву.
Йорданм

Відповіді:


27

Це можна зробити за допомогою списку клавіш масиву . На bashчоловіковій сторінці:

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

Список ключів масиву . Якщо name є змінною масиву, розширюється до списку індексів (ключів) масиву, присвоєних імені. Якщо ім'я не є масивом, він розширюється на те, 0якщо ім'я встановлено, а інше недійсне. Коли @використовується і розширення з’являється в подвійних лапках, кожна клавіша розширюється на окреме слово.

Для вашого прикладу:

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

Це призводить до:

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

Зауважте, що це також працює для непослідовних індексів:

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

Це призводить до:

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

1
Незважаючи на те, що ця відповідь досягає бажаного результату, заява printf надмірно не вражає. Наприклад: printf "$i=(${AR[i]})\n"або echo "$i=(${ARi]})"обидва дають трохи додаткового, показуючи, як отримати ключ & var, але строго кажучи echo "$i", відповів би на ОП. Решта - "bash fu" :)
dimmech

5

Крім відповіді jordanm, ви також можете зробити Cподібний цикл у bash:

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

1

ви можете зробити щось подібне:

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

вихід:

0
1
2
3

1
Що це говорить про  те, що відповідь pfnuesel   вже не говорить?
G-Man каже: "Відновіть Моніку"

Я можу помилитися, але чи відповідає pfnuesels не переосмислюючи довжину масиву на кожній ітерації?
Кріс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.