Is het mogelijk om multidimensionale arrays te maken in bash-scripting?
Dit zijn mijn 3 arrays :
arrayCITY=( NewYork LasVegas Detroit ) arraySTREET=( RoadStreet TreeStreet HighStreet ) arrayNUMBER=( 20 455 300 )
Nu wil ik deze 3 arrays in slechts één array plaatsen – is dit mogelijk? Dan wil ik ze laten zien in een txt-bestand. Nu doe ik het als volgt:
for ((i=0; i<${#arrayCITY[*]}; i++));do echo "${arrayCITY[i]} ${arraySTREET[i]} ${arrayNUMBER[i]}" >> TEXT.txt done
Antwoord
Van 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.
Sleutelzin:
Bash biedt eendimensionale geïndexeerde en associatieve array-variabelen.
Dus nee, bash ondersteunt geen multidimensionale arrays.
Answer
Ik kwam dit zojuist tegen. Er is een vrij eenvoudige oplossing die voor mij werkte. Ik wilde een array gebruiken die een apparaatnaam en een schermpositie bevatte om een key map voor het apparaat weer te geven. Ik deed het volgende: ik voegde de apparaatnaam en de bijbehorende schermpositie samen tot één tekenreeks, met behulp van een scheidingsteken (in mijn geval gebruikte ik .
) waarvan ik wist dat ze in geen van mijn waarden zouden voorkomen. Vervolgens heb ik cut
gebruikt om de samengestelde waarden indien nodig op te splitsen in hun componenten. Er is misschien een schonere en eenvoudigere manier om dit te doen, maar dit is slechts om te laten zien dat je in zekere zin een multidimensionale array kunt maken in bash, ook al ondersteunt het dit niet:
#!/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
Dit lijkt enigszins op Coop.Computers antwoord .
Antwoord
Hier is een oplossing die voor mij werkt. Als we de array voor het eerst als volgt instellen:
arrayCSR=( Placeholder_for_0_spot NewYork RoadStreet 20 LasVegas TreeStreet 455 Detroit HighStreet 300 )
De tijdelijke aanduiding is aanwezig om te voorkomen dat u met een 0-index te maken krijgt.
Dan is elke " rij " alles dat kan worden gedeeld door 3, en elke " kolom " is 1 of 2 minder dan de " rij " nummer.
${arrayCSR[${3}]} is 20 ${arrayCSR[${2}]} is RoadStreet ${arrayCSR[${1}]} is NewYork
Een voorbeeldscript staat hieronder:
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
Dus elke index die kan delen door 3 geeft een " rij ", en ook de derde " kolom " in de rij. Om de tweede en eerste " kolom " te krijgen, trekt u 1 of 2 dienovereenkomstig af.
Dit kan ook omhoog schalen indien nodig.
Update: hieronder staat de code die ik gebruik om te laden en een reeks vervangende tekenreeksen voor bestandsnamen. De eerste array wordt geladen uit een bestand en vervolgens opgesplitst in 2 aparte arrays.
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
Reacties
- Dat ' is een handige manier om een 2D-array te vervalsen als de lengte van alle elementen bekend is (en consistent), maar zal natuurlijk niet werken voor elementen met variabele lengte.
- Voor mij zou de eenvoudige manier zijn om gewoon 3 arrays te gebruiken, waarbij de index de gemeenschappelijke link tussen hen is.
Answer
Hoe graag ik Bash ook vind, het is logisch om af en toe over te schakelen naar andere talen. Dit is redelijk eenvoudig met een woordenboek in 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"]))
Als je dit uitvoert, krijg je:
./cities.py New York: Roadstreet 20 Las Vegas: TreeStreet 455