Acessando variável de índice de matriz do loop de script do shell bash?


18

Eu quero acessar a variável de índice da matriz durante um loop através de uma matriz no meu script de shell bash.

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

O resultado do script acima é:

foo
bar
baz
bat

O resultado que procuro é:

0
1
2
3

Como altero meu script para conseguir isso?


6
Observe também que você basicamente nunca deseja, em "${array[*]}"vez de "${array[@]}". Usar em *vez de @mais ou menos trata-o como uma sequência em vez de uma matriz.
Jordanm 23/04

Respostas:


23

Você pode fazer isso usando a Lista de chaves da matriz . Na bashpágina do manual:

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

Lista de chaves de matriz . Se nome é uma variável de matriz, expande para a lista de índices de matriz (chaves) atribuídos no nome. Se nome não for uma matriz, expande para 0se o nome estiver definido e nulo caso contrário. Quando @é usada e a expansão aparece entre aspas duplas, cada tecla se expande para uma palavra separada.

Para o seu exemplo:

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

Isto resulta em:

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

Observe que isso também funciona para índices não sucessivos:

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

Isto resulta em:

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

1
Embora essa resposta atinja o resultado desejado, ela é desnecessariamente ofuscada pela instrução printf. Por exemplo: printf "$i=(${AR[i]})\n"ou echo "$i=(${ARi]})"ambos dão um pouco mais, mostrando como obter key & var, mas, estritamente falando echo "$i", teria respondido ao OP. O resto é "fu bash" :)
dimmech

6

Além da resposta de jordanm, você também pode fazer um Cloop semelhante em bash:

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

1

você pode fazer algo assim:

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

resultado:

0
1
2
3

1
O que isso diz que  a resposta de pfnuesel   ainda não diz?
G-Man diz 'Restabelecer Monica

Posso estar enganado, mas o pfnuesels responde não reavalia o comprimento do array em cada iteração?
Chris
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.