combinando 3 matrices separadas en una matriz multidimensional en bash

¿Es posible crear matrices multidimensionales en bash scripting?

Estas son mis 3 matrices :

arrayCITY=( NewYork LasVegas Detroit ) arraySTREET=( RoadStreet TreeStreet HighStreet ) arrayNUMBER=( 20 455 300 ) 

Ahora quiero poner estas 3 matrices en una sola matriz, ¿es esto posible? Entonces quiero mostrarlos en un archivo txt. Ahora lo hago así:

for ((i=0; i<${#arrayCITY[*]}; i++));do echo "${arrayCITY[i]} ${arraySTREET[i]} ${arrayNUMBER[i]}" >> TEXT.txt done 

Responder

De man 1 bash:

Arrays Bash provides one-dimensional indexed and associative array variables. Any variable may be used as an indexed array; the declare builtin will explicitly declare an array. There is no maximum limit on the size of an array, nor any requirement that members be indexed or assigned contiguously. Indexed arrays are referenced using integers (including arithmetic expressions) and are zero-based; associative arrays are referenced using arbitrary strings. Unless otherwise noted, indexed array indices must be non-negative integers. 

Frase clave:

Bash proporciona variables de matriz unidimensionales indexadas y asociativas.

Entonces, no, bash no admite matrices multidimensionales.

Respuesta

Me encontré con esto hace un momento. Hay una solución bastante simple que funcionó para mí. Quería usar una matriz que contuviera un nombre de dispositivo y una posición de pantalla para mostrar un mapa de teclas para el dispositivo. Hice lo siguiente: concatené el nombre del dispositivo y la posición de la pantalla asociada en una sola cadena, usando un delimitador (en mi caso, usé . ) que sabía que no aparecería en ninguno de mis valores. Luego usé cut para dividir los valores compuestos en sus componentes cuando fue necesario. Puede haber una forma más limpia y sencilla de hacer esto, pero esto es solo para mostrar que puedes crear una matriz multidimensional, de alguna manera, en bash, aunque no lo admita:

#!/bin/bash # List of devices and screen positions for key maps. DEV_LIST=( g13.+2560+30 g510s.+3160+30 g502.+2560+555 ) # This just echoes the device name and the screen position. for DEV in "${DEV_LIST[@]}"; do DEVICE=$(echo $DEV | cut -f1 -d.) SCREEN_POSITION=$(echo $DEV | cut -f2 -d.) echo "$DEVICE" echo "$SCREEN_POSITION" done exit 

Esto es algo similar a Coop.Computers answer .

Answer

Aquí hay una solución que me funciona. Si primero configuramos la matriz de esta manera:

  arrayCSR=( Placeholder_for_0_spot NewYork RoadStreet 20 LasVegas TreeStreet 455 Detroit HighStreet 300 )  

El marcador de posición está ahí para evitar tener que lidiar con un índice 0.

Entonces, cada " fila " es cualquier cosa que pueda ser dividido por 3, y cada " columna " es 1 o 2 menos que la " row " número.

${arrayCSR[${3}]} is 20 ${arrayCSR[${2}]} is RoadStreet ${arrayCSR[${1}]} is NewYork 

A continuación se muestra un script de muestra:

  arrayCSR=( CsR NewYork RoadStreet 20 LasVegas TreeStreet 455 Detroit HighStreet 300 ) for p in $( seq 1 ${#arrayCSR[*]} ) do if [[ "${arrayCSR[${p}]}" == "" ]] # Don"t run if empty then true elif [[ $((p % 3 )) -eq 0 ]] # We have 3 "columns" in the array then echo " ${arrayCSR[$(( p - 2 ))]} ${arrayCSR[$(( p - 1))]} ${arrayCSR[${p}]}" fi done  

Entonces, cualquier índice que pueda dividirse por 3 indica una " fila ", y también la tercera " columna " en la fila. Para obtener la segunda y la primera " columna ", reste 1 o 2 según corresponda.

Esto también se puede ampliar si es necesario.

Actualización: A continuación se muestra el código que utilizo para cargar y una matriz de reemplazos de cadenas para los nombres de archivo. La primera matriz se carga desde un archivo y luego se divide en 2 matrices separadas.

  readarray -t string_replace < ~/scripts/string_replace.lst # List of things to remove from name for p in $( seq 0 ${#string_replace[*]} ); do old_name_element[${p}]="${string_replace[${p}]%%,*}" new_name_element[${p}]="${string_replace[${p}]:$((${#old_name_element[${p}]}+1))}" done string_replace=() # Clear old array  

Comentarios

  • Que ' es una forma sencilla de falsificar una matriz 2D si se conoce la longitud de todos los elementos (y coherente), pero, por supuesto, no funcionará para elementos de longitud variable.
  • Para mí, la forma más sencilla sería utilizar 3 matrices, siendo el índice el vínculo común entre ellas.

Responder

Por mucho que me guste Bash, tiene sentido cambiar a veces a otros idiomas. Esto es bastante sencillo usando un diccionario en Python:

#!/usr/bin/env python3 cities = { "New York": { "Street": "Roadstreet", "Number": 20 }, "Las Vegas": { "Street": "TreeStreet", "Number": 455 } } for city in cities: print(str(city) + ": " + str(cities[city]["Street"]) + " " + str(cities[city]["Number"])) 

Ejecutar esto produce:

./cities.py New York: Roadstreet 20 Las Vegas: TreeStreet 455 

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *