¿Acceso a la variable de índice de matriz desde el bucle de script de shell bash?

19

Quiero acceder a la variable de índice de matriz mientras hago un bucle a través de una matriz en mi script de shell bash.

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

El resultado del script anterior es:

foo
bar
baz
bat

El resultado que busco es:

0
1
2
3

¿Cómo modifico mi script para lograr esto?

Cortacésped
fuente
77
También tenga en cuenta que básicamente nunca quiere en "${array[*]}"lugar de "${array[@]}". Usar en *lugar de @más o menos lo trata como una cadena en lugar de una matriz.
jordanm

Respuestas:

27

Puede hacerlo utilizando la Lista de claves de matriz . Desde la bashpágina del manual:

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

Lista de claves de matriz . Si nombre es una variable de matriz, se expande a la lista de índices de matriz (claves) asignados en el nombre. Si el nombre no es una matriz, se expande a 0si el nombre está establecido y nulo de lo contrario. Cuando @se usa y la expansión aparece entre comillas dobles, cada tecla se expande a una palabra separada.

Por su ejemplo:

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

Esto resulta en:

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

Tenga en cuenta que esto también funciona para índices no sucesivos:

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

Esto resulta en:

${AR[3]}=foo
${AR[5]}=bar
${AR[7]}=bat
${AR[25]}=baz
jordanm
fuente
1
Aunque esta respuesta logra el resultado deseado, la declaración printf la ofusca innecesariamente. Por ejemplo: printf "$i=(${AR[i]})\n"o echo "$i=(${ARi]})"ambos dan un poco más al mostrar cómo obtener key & var, pero estrictamente hablando echo "$i"habría respondido al OP. El resto es "bash fu" :)
dimmech
5

Además de la respuesta de jordanm, también puede hacer un Cciclo similar en bash:

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

puedes hacer algo como esto:

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

salida:

0
1
2
3
F.9876
fuente
1
¿Qué dice esto que  la respuesta de pfnuesel   no dice ya?
G-Man dice 'Reincorporar a Monica' el
Puedo estar equivocado, pero ¿la respuesta de pfnuesels no reevalúa la longitud de la matriz en cada iteración?
Chris