Arrays en Bash
Las nuevas versiones de Bash soportan matrices unidimensionales. Los elementos de matriz se pueden inicializar con la notación variable[xx].
Alternativamente, un script puede introducir todo el conjunto con una declaración explícita de variables. Para recuperar el contenido de un elemento del array, se usan las llaves y corchetes de la siguiente manera: ${elemento[xx]}.
Ejemplos de uso de arrays:
#!/bin/bash area[11]=23 area[13]=37 area[51]=UFOs # No hace falta que sean consecutivos. echo -n "area[11] = " echo ${area[11]} # Se necesitan {llaves}. echo -n "area[13] = " echo ${area[13]} echo "Contents of area[51] are ${area[51]}." area[5]=$((${area[11]}+${area[13]})) area2=( zero one two three four ) # otra manera de inicializar un array echo ${area2[0]} area3=([17]=seventeen [24]=twenty-four) # y otra manera, esta vez, indicando la posición de los elementos echo ${area3[17]} echo ${#area3[@]} # Longitud del array
Un ejemplo práctico y error común puede producirse al querer guardar nombres de ficheros en un array:
$ ficheros=$(ls) # MAL. Se guarda en una variable una lista de ficheros, pero no un array $ ficheros=($(ls)) # Todavía MAL. Si hay ficheros con espacios en sus nombres dará problemas. $ files=(*) # Bien!. El asterisco * permite guardar cada nombre de fichero en una posición del array, aunque tenga espacios.
Una manera de recorrer los elementos de un array:
$ for file in "${myfiles[@]}"; do > cp "$file" /backups/ > done
Simular Arrays multidimensionales
Es posible simular los arrays multidimensionales con bash. Lo que en c o java podríamos así:
matriz[3][5]=34;
En Bash lo ponemos así:
$ matriz[5*$ancho+3]=34
En este caso, $ancho es la anchura que queremos simular en la matriz.
Arrays como parámetros
Si pasamos un array como parámetro, una función puede interpretarlo como una sucesión de parámetros, algo que no entiende o una cadena con espacios, pero no un array:
#!/bin/bash func() { echo $1 echo $@ } a=(1 2 3 4) func $a # MAL, retorna 1 func ${a[@]} # MAL, retorna 1 func "${a[@]}" # MAL, retorna 1
Ninguna de las anteriores opciones han servido para pasar correctamente el array. Podríamos usar $@ si sólo enviamos un array, pero si queremos enviar dos o más, nos dará problemas.
#!/bin/bash func() { array=("${!1}") echo ${array[@]} } a=(1 2 3 4) func $a # MAL func ${a[@]} # MAL func "${a[@]}" # MAL func 'a[@]' # Bien
Lo que ha pasado es que le pasamos el nombre del array con la @, entonces el ! expande la variable $1 antes de interpretarla. Es decir, ("${!1}") se convierte en ("${a[@]}") que se interpreta como (1 2 3 4) y se le pasa a la variable nueva array.
Observa porqué pasa esto:
$ baba=booba $ variable=baba $ echo ${variable} # baba $ echo ${!variable} # booba
Se trata de una referencia indirecta.
¿Cual es el problema?
http://stackoverflow.com/questions/1063347/passing-arrays-as-parameters-in-bash
http://stackoverflow.com/questions/8082947/how-to-pass-an-array-to-a-bash-function
Arrays Asociativos
declare -a ARRAY #Declara un array indexado. No es necesario declararlo siempre, ya que es la opción por defecto. declare -A ARRAY #Declara un array asociativo. Es la única manera de declararlos.
Veamos este ejemplo sacado de [1]
declare -A sentence sentence[Begin]='Be liberal in what' sentence[Middle]='you accept, and conservative' sentence[End]='in what you send' sentence['Very end']=...
Otra manera:
sentence=([End]="in what you send" [Middle]="you accept, and conservative " [Begin]="Be liberal in what " ["Very end"]="...")