Czy możliwe jest tworzenie wielowymiarowych tablic w skryptach basha?
To są moje 3 tablice :
arrayCITY=( NewYork LasVegas Detroit ) arraySTREET=( RoadStreet TreeStreet HighStreet ) arrayNUMBER=( 20 455 300 )
Teraz chcę umieścić te 3 tablice w jednej tablicy – czy to możliwe? Następnie chcę je pokazać w pliku txt. Teraz robię to w ten sposób:
for ((i=0; i<${#arrayCITY[*]}; i++));do echo "${arrayCITY[i]} ${arraySTREET[i]} ${arrayNUMBER[i]}" >> TEXT.txt done
Odpowiedź
Od 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.
Fraza kluczowa:
Bash zapewnia jednowymiarowe indeksowane i asocjacyjne zmienne tablicowe.
Więc nie, bash nie obsługuje wielowymiarowych tablic.
Odpowiedź
Natknąłem się na to właśnie teraz. Jest dość proste rozwiązanie, które zadziałało. Chciałem użyć tablicy, która zawierałaby nazwę urządzenia i pozycję na ekranie, aby wyświetlić mapę klawiszy dla urządzenia. Wykonałem następujące czynności: połączyłem nazwę urządzenia i skojarzoną z nią pozycję ekranu w jeden ciąg, używając separatora (w moim przypadku użyłem .
), o których wiedziałem, że nie pojawią się w żadnej z moich wartości. Następnie użyłem cut
, aby w razie potrzeby rozdzielić wartości złożone na ich składniki. Może istnieć bardziej przejrzysty i prostszy sposób, aby to zrobić, ale to tylko po to, aby pokazać, że w bash można utworzyć tablicę wielowymiarową, nawet jeśli jej nie obsługuje:
#!/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
To jest trochę podobne do odpowiedzi Coop.Computer .
Odpowiedź
Oto „rozwiązanie, które działa dla mnie. Jeśli najpierw ustawimy tablicę w ten sposób:
arrayCSR=( Placeholder_for_0_spot NewYork RoadStreet 20 LasVegas TreeStreet 455 Detroit HighStreet 300 )
Symbol zastępczy jest tam aby uniknąć konieczności zajmowania się indeksem 0.
Następnie każdy " wiersz " to wszystko, co może być podzielone przez 3, a każda " kolumna " jest o 1 lub 2 mniejsza niż " wiersz " numer.
${arrayCSR[${3}]} is 20 ${arrayCSR[${2}]} is RoadStreet ${arrayCSR[${1}]} is NewYork
Przykładowy skrypt jest poniżej:
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
Zatem każdy indeks, który można podzielić przez 3, oznacza " wiersz ", a także trzecia " kolumna " w wierszu. Aby uzyskać drugą i pierwszą " kolumnę ", odejmij odpowiednio 1 lub 2.
Można to również zwiększyć w razie potrzeby.
Aktualizacja: Poniżej znajduje się kod, którego używam do ładowania i tablica zamienników ciągów dla nazw plików. Pierwsza tablica jest ładowana z pliku, a następnie dzielona na 2 oddzielne tablice.
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
Komentarze
- To ' to świetny sposób na sfałszowanie tablicy 2D, jeśli znana jest długość wszystkich elementów (i spójne), ale oczywiście nie będzie działać w przypadku elementów o zmiennej długości.
- Dla mnie najprostszym sposobem byłoby użycie 3 tablic, z indeksem będącym wspólnym łączem między nimi.
Odpowiedź
Chociaż lubię Bash, warto czasami przełączyć się na inny język. Jest to dość proste przy użyciu słownika w Pythonie:
#!/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"]))
Uruchomienie tego daje:
./cities.py New York: Roadstreet 20 Las Vegas: TreeStreet 455