Este posibil să creăm matrice multidimensionale în scriptarea bash?
Acestea sunt cele 3 matrice ale mele :
arrayCITY=( NewYork LasVegas Detroit ) arraySTREET=( RoadStreet TreeStreet HighStreet ) arrayNUMBER=( 20 455 300 )
Acum vreau să pun aceste 3 matrice într-o singură matrice – este posibil? Apoi vreau să le arăt într-un fișier txt. Acum o fac așa:
for ((i=0; i<${#arrayCITY[*]}; i++));do echo "${arrayCITY[i]} ${arraySTREET[i]} ${arrayNUMBER[i]}" >> TEXT.txt done
Răspuns
Din 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.
Expresie cheie:
Bash oferă variabile de matrice indexate și asociative unidimensionale.
Deci, nu, bash nu acceptă tablouri multi-dimensionale.
Răspuns
Am dat peste asta chiar acum. Există o soluție destul de simplă care a funcționat pentru mine. Am vrut să folosesc o matrice care conținea un nume de dispozitiv și o poziție a ecranului pentru a afișa o hartă cheie pentru dispozitiv. Am făcut următoarele: am concatenat numele dispozitivului și poziția ecranului asociat într-un singur șir, folosind un delimitator (în cazul meu, am folosit .
) despre care știam că nu vor apărea în niciuna dintre valorile mele. Apoi am folosit cut
pentru a sparge valorile compozite în componentele lor atunci când este necesar. S-ar putea să existe o modalitate mai curată și mai simplă de a face acest lucru, dar aceasta este doar pentru a arăta că puteți crea o matrice multidimensională, într-un fel, în bash, chiar dacă nu o acceptă:
#!/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
Acest lucru este oarecum similar cu Răspunsul Coop.Computer .
Răspuns
Aici „o soluție care funcționează pentru mine. Dacă configurăm mai întâi matricea astfel:
arrayCSR=( Placeholder_for_0_spot NewYork RoadStreet 20 LasVegas TreeStreet 455 Detroit HighStreet 300 )
Substituentul este acolo pentru a evita să aveți de-a face cu un index 0.
Apoi, fiecare " rând " este orice poate fi împărțit la 3 și fiecare " coloană " este cu 1 sau 2 mai mică decât " rând " număr.
${arrayCSR[${3}]} is 20 ${arrayCSR[${2}]} is RoadStreet ${arrayCSR[${1}]} is NewYork
Un exemplu de script este mai jos:
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
Deci orice index care poate împărți la 3 indică un " rând ", precum și a treia " coloană " din rând. Pentru a obține a doua și prima " coloană ", scădeți 1 sau 2 în consecință.
Acest lucru poate crește și dacă este necesar.
Actualizare: Mai jos este codul pe care îl folosesc pentru a încărca și o serie de înlocuiri de șiruri pentru numele fișierelor. Prima matrice este încărcată dintr-un fișier, apoi este împărțită în 2 tablouri separate.
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
Comentarii
- Că ' este un mod elegant de a falsifica o matrice 2D dacă se cunoaște lungimea tuturor elementelor (și consecvent), dar, desigur, nu va funcționa pentru elementele cu lungime variabilă.
- Pentru mine, modul simplu ar fi să folosesc doar 3 tablouri, indexul fiind legătura comună dintre ele.
Răspuns
Oricât de mult îmi place Bash, are sens să treceți uneori la alte limbi. Acest lucru este destul de simplu folosind un dicționar în 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"]))
Rularea acestui lucru produce:
./cities.py New York: Roadstreet 20 Las Vegas: TreeStreet 455