É possível criar arrays multidimensionais em script bash?
Esses são meus 3 arrays :
arrayCITY=( NewYork LasVegas Detroit ) arraySTREET=( RoadStreet TreeStreet HighStreet ) arrayNUMBER=( 20 455 300 )
Agora eu quero colocar esses 3 arrays em apenas um array – isso é possível? Então eu quero mostrá-los em um arquivo txt. Agora eu faço assim:
for ((i=0; i<${#arrayCITY[*]}; i++));do echo "${arrayCITY[i]} ${arraySTREET[i]} ${arrayNUMBER[i]}" >> TEXT.txt done
Resposta
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-chave:
O Bash fornece variáveis de matriz associativa e indexadas unidimensionais.
Portanto, não, o bash não oferece suporte a matrizes multidimensionais.
Resposta
Acabei de encontrar isso. Existe uma solução bastante simples que funcionou para mim. Eu queria usar uma matriz que contivesse um nome de dispositivo e uma posição na tela para exibir um mapa de teclas para o dispositivo. Fiz o seguinte: concatenei o nome do dispositivo e a posição da tela associada em uma única string, usando um delimitador (no meu caso, usei .
) que eu sabia que não apareceria em nenhum dos meus valores. Em seguida, usei cut
para separar os valores compostos em seus componentes quando necessário. Pode haver uma maneira mais limpa e simples de fazer isso, mas isso é apenas para mostrar que você pode criar um array multidimensional, de certa forma, em bash, mesmo que não seja compatível:
#!/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
Isso é um pouco semelhante à Resposta do Coop.Computer .
Resposta
Aqui está uma solução que funciona para mim. Se primeiro configurarmos a matriz assim:
arrayCSR=( Placeholder_for_0_spot NewYork RoadStreet 20 LasVegas TreeStreet 455 Detroit HighStreet 300 )
O marcador está lá para evitar ter que lidar com um índice 0.
Então, cada " linha " é qualquer coisa que possa ser dividido por 3, e cada " coluna " é 1 ou 2 menor do que " linha " número.
${arrayCSR[${3}]} is 20 ${arrayCSR[${2}]} is RoadStreet ${arrayCSR[${1}]} is NewYork
Um exemplo de script está abaixo:
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
Portanto, qualquer índice que possa ser dividido por 3 indica uma " linha ", e também a terceira " coluna " na linha. Para obter a segunda e a primeira " coluna ", subtraia 1 ou 2 de acordo.
Isso também pode aumentar se necessário.
Atualização: abaixo está o código que eu uso para carregar e uma matriz de substituições de string para nomes de arquivo. A primeira matriz é carregada de um arquivo e, em seguida, é dividida em 2 matrizes 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
Comentários
- Isso ' é uma maneira bacana de falsificar uma matriz 2D se o comprimento de todos os elementos for conhecido (e consistente), mas é claro que não funcionará para elementos de comprimento variável.
- Para mim, a maneira mais simples seria usar apenas 3 matrizes, com o índice sendo o elo comum entre eles.
Resposta
Por mais que eu goste do Bash, às vezes faz sentido mudar para outros idiomas. Isso é bastante simples usando um dicionário em 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"]))
Executar isso resulta em:
./cities.py New York: Roadstreet 20 Las Vegas: TreeStreet 455