Trabajar con matrices en secuencias de comandos de Shell de Linux – Parte 8
No podemos imaginar un lenguaje de programación sin el concepto de matrices. No importa cómo se implementen entre varios idiomas. En cambio, las matrices nos ayudan a consolidar datos, similares o diferentes, bajo un nombre simbólico.
En este caso, como nos preocupan los scripts de shell, este artículo le ayudará a jugar con algunos scripts de shell que utilizan este concepto de matrices.
Inicialización y uso de matrices
Con las versiones más nuevas de bash, admite matrices unidimensionales. Una matriz se puede declarar explícitamente mediante el shell integrado declare.
declare -a var
Pero no es necesario declarar variables de matriz como se indicó anteriormente. Podemos insertar elementos individuales en la matriz directamente de la siguiente manera.
var[XX]=<value>
donde 'XX' denota el índice de la matriz. Para desreferenciar elementos de la matriz, utilice la sintaxis de llaves, es decir
${var[XX]}
Nota: la indexación de matrices siempre comienza con 0.
Otra forma conveniente de inicializar una matriz completa es utilizar el par de paréntesis como se muestra a continuación.
var=( element1 element2 element3 . . . elementN )
Existe otra forma más de asignar valores a las matrices. Esta forma de inicialización es una subcategoría del método explicado anteriormente.
array=( [XX]=<value> [XX]=<value> . . . )
También podemos leer/asignar valores a la matriz durante el tiempo de ejecución usando el shell integrado read.
read -a array
Ahora, al ejecutar la declaración anterior dentro de un script, espera alguna entrada. Necesitamos proporcionar los elementos de la matriz separados por espacios (y no por retorno de carro). Después de ingresar los valores, presione Enter para finalizar.
Para recorrer los elementos de la matriz también podemos usar el bucle for.
for i in “${array[@]}”
do
#access each element as $i. . .
done
El siguiente script resume el contenido de esta sección en particular.
#!/bin/bash
array1[0]=one
array1[1]=1
echo ${array1[0]}
echo ${array1[1]}
array2=( one two three )
echo ${array2[0]}
echo ${array2[2]}
array3=( [9]=nine [11]=11 )
echo ${array3[9]}
echo ${array3[11]}
read -a array4
for i in "${array4[@]}"
do
echo $i
done
exit 0
Varias operaciones en matrices
Muchas de las operaciones de cadenas estándar funcionan en matrices. Mire el siguiente script de muestra que implementa algunas operaciones en matrices (incluidas operaciones de cadenas).
#!/bin/bash
array=( apple bat cat dog elephant frog )
#print first element
echo ${array[0]}
echo ${array:0}
#display all elements
echo ${array[@]}
echo ${array[@]:0}
#display all elements except first one
echo ${array[@]:1}
#display elements in a range
echo ${array[@]:1:4}
#length of first element
echo ${#array[0]}
echo ${#array}
#number of elements
echo ${#array[*]}
echo ${#array[@]}
#replacing substring
echo ${array[@]//a/A}
exit 0
A continuación se muestra el resultado producido al ejecutar el script anterior.
apple
apple
apple bat cat dog elephant frog
apple bat cat dog elephant frog
bat cat dog elephant frog
bat cat dog elephant
5
5
6
6
Apple bAt cAt dog elephAnt frog
Creo que no tiene sentido explicar el guión anterior en detalle ya que se explica por sí mismo. Si es necesario, dedicaré una parte de esta serie exclusivamente a la manipulación de cuerdas.
Sustitución de comandos con matrices
La sustitución de comandos asigna la salida de uno o varios comandos a otro contexto. Aquí, en este contexto de matrices, podemos insertar la salida de los comandos como elementos individuales de las matrices. La sintaxis es la siguiente.
array=( $(command) )
De forma predeterminada, el contenido de la salida del comando separado por espacios en blanco se inserta en una matriz como elementos individuales. El siguiente script enumera el contenido de un directorio, que son archivos con permisos 755.
#!/bin/bash
ERR=27
EXT=0
if [ $# -ne 1 ]; then
echo "Usage: $0 <path>"
exit $ERR
fi
if [ ! -d $1 ]; then
echo "Directory $1 doesn't exists"
exit $ERR
fi
temp=( $(find $1 -maxdepth 1 -type f) )
for i in "${temp[@]}"
do
perm=$(ls -l $i)
if [ `expr ${perm:0:10} : "-rwxr-xr-x"` -eq 10 ]; then
echo ${i##*/}
fi
done
exit $EXT
Simulación de matrices bidimensionales
Podemos representar fácilmente una matriz bidimensional usando una matriz unidimensional. En orden principal de filas, los elementos de representación en cada fila de una matriz se almacenan progresivamente en índices de matriz de manera secuencial. Para una matriz mXn, la fórmula de la misma se puede escribir como.
matrix[i][j]=array[n*i+j]
Mire otro script de muestra para sumar 2 matrices e imprimir la matriz resultante.
#!/bin/bash
read -p "Enter the matrix order [mxn] : " t
m=${t:0:1}
n=${t:2:1}
echo "Enter the elements for first matrix"
for i in `seq 0 $(($m-1))`
do
for j in `seq 0 $(($n-1))`
do
read x[$(($n*$i+$j))]
done
done
echo "Enter the elements for second matrix"
for i in `seq 0 $(($m-1))`
do
for j in `seq 0 $(($n-1))`
do
read y[$(($n*$i+$j))]
z[$(($n*$i+$j))]=$((${x[$(($n*$i+$j))]}+${y[$(($n*$i+$j))]}))
done
done
echo "Matrix after addition is"
for i in `seq 0 $(($m-1))`
do
for j in `seq 0 $(($n-1))`
do
echo -ne "${z[$(($n*$i+$j))]}\t"
done
echo -e "\n"
done
exit 0
Aunque existen limitaciones para implementar matrices dentro de scripts de shell, resulta útil en algunas situaciones, especialmente cuando manejamos la sustitución de comandos. Desde un punto de vista administrativo, el concepto de matrices allanó el camino para el desarrollo de muchos scripts en segundo plano en sistemas GNU/Linux.