Är det möjligt att skapa flerdimensionella matriser i bash-skript?
Dessa är mina 3 matriser :
arrayCITY=( NewYork LasVegas Detroit ) arraySTREET=( RoadStreet TreeStreet HighStreet ) arrayNUMBER=( 20 455 300 )
Nu vill jag placera dessa tre matriser i bara en matris – är det möjligt? Sedan vill jag visa dem i en txt-fil. Nu gör jag det så här:
for ((i=0; i<${#arrayCITY[*]}; i++));do echo "${arrayCITY[i]} ${arraySTREET[i]} ${arrayNUMBER[i]}" >> TEXT.txt done
Svar
Från 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.
Nyckelfras:
Bash tillhandahåller endimensionella indexerade och associerande matrisvariabler.
Så nej, bash stöder inte flerdimensionella matriser.
Svar
Jag stötte på det här just nu. Det finns en ganska enkel lösning som fungerade för mig. Jag ville använda en array som innehöll ett enhetsnamn och en skärmposition för att visa en nyckelkarta för enheten. Jag gjorde följande: Jag sammanfogade enhetsnamnet och tillhörande skärmposition i en enda sträng med en avgränsare (i mitt fall använde jag .
) som jag visste inte skulle visas i något av mina värden. Sedan använde jag cut
för att bryta samman de sammansatta värdena i sina komponenter vid behov. Det kan finnas ett renare och enklare sätt att göra detta, men detta är bara för att visa att du kan skapa en flerdimensionell matris, på ett sätt, i bash, även om den inte stöder den:
#!/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
Detta liknar något Coop.Computers svar .
Svar
Här ”är en lösning som fungerar för mig. Om vi först ställer in matrisen så här:
arrayCSR=( Placeholder_for_0_spot NewYork RoadStreet 20 LasVegas TreeStreet 455 Detroit HighStreet 300 )
Platshållaren är där för att undvika att behöva hantera ett 0-index.
Sedan är varje " rad " allt som kan vara dividerat med 3 och varje " kolumn " är 1 eller 2 mindre än " rad " nummer.
${arrayCSR[${3}]} is 20 ${arrayCSR[${2}]} is RoadStreet ${arrayCSR[${1}]} is NewYork
Ett exempelskript är nedan:
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
Så vilket index som kan dela med 3 indikerar en " rad " och även den tredje " kolumn " i raden. För att få den andra och första " kolumn ", subtrahera 1 eller 2 därefter.
Detta kan också skala upp om det behövs.
Uppdatering: Nedan följer kod som jag använder för att ladda och radera strängersättningar för filnamn. Den första matrisen laddas från en fil och delas sedan upp i två separata matriser.
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
Kommentarer
- Att ' är ett snyggt sätt att fejka en 2D-array om längden på alla element är känd (och konsekvent), men kommer naturligtvis inte att fungera för element med variabel längd.
- För mig skulle det enkla sättet vara att bara använda tre matriser, med indexet som den gemensamma länken mellan dem.
Svar
Så mycket som jag gillar Bash är det vettigt att ibland byta till andra språk. Detta är ganska enkelt med en ordbok i 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"]))
Att köra detta ger:
./cities.py New York: Roadstreet 20 Las Vegas: TreeStreet 455