Podstawowym problemem jest to, że twórcy bashów, którzy zaprojektowali / zaimplementowali tablice, naprawdę spieprzyli puchata. Uznali, że ${array}
to krótka ręka ${array[0]}
, co było poważnym błędem. Zwłaszcza, jeśli weźmiesz pod uwagę, że ${array[0]}
nie ma to znaczenia i zwraca pusty ciąg, jeśli typ tablicy jest asocjacyjny.
Przypisanie tablicy ma postać, w array=(value1 ... valueN)
której wartość ma składnię [subscript]=string
, tym samym przypisując wartość bezpośrednio do określonego indeksu w tablicy. To sprawia, że mogą istnieć dwa typy tablic, indeksowane numerycznie i indeksowane hash (zwane tablicami asocjacyjnymi w języku bash). Dzięki temu możesz tworzyć rzadkie tablice indeksowane numerycznie. Wyjście z tej [subscript]=
części jest krótką ręką dla tablicy indeksowanej numerycznie, zaczynając od porządkowego indeksu 0 i zwiększając każdą nową wartość w instrukcji przypisania.
Dlatego ${array}
powinien oceniać całą tablicę, indeksy i wszystkie. Powinien być odwrócony do instrukcji przypisania. Każdy student CS-dur trzeciego roku powinien o tym wiedzieć. W takim przypadku ten kod działałby dokładnie tak, jak można się spodziewać:
declare -A foo bar
foo=${bar}
Następnie przekazywanie tablic według wartości do funkcji i przypisywanie jednej tablicy do drugiej działałoby tak, jak dyktuje reszta składni powłoki. Ale ponieważ nie zrobili tego dobrze, operator przypisania =
nie działa dla tablic, a tablic nie można przekazywać wartościami do funkcji lub do podpowłok lub generalnie danych wyjściowych ( echo ${array}
) bez kodu, który przejrzałby to wszystko.
Tak więc, jeśli zrobiono to dobrze, następujący przykład pokazałby, jak użyteczność tablic w bashu może być znacznie lepsza:
simple=(first=one second=2 third=3)
echo ${simple}
wynikowy wynik powinien wynosić:
(first=one second=2 third=3)
Następnie tablice mogłyby korzystać z operatora przypisania i być przekazywane przez wartość do funkcji, a nawet innych skryptów powłoki. Łatwo przechowywane przez wyjście do pliku i łatwe ładowanie z pliku do skryptu.
declare -A foo
read foo <file
Niestety, zawiódł nas świetny zespół programistów bash.
W związku z tym, aby przekazać tablicę do funkcji, jest tak naprawdę tylko jedna opcja, a mianowicie użycie funkcji nameref:
function funky() {
local -n ARR
ARR=$1
echo "indexes: ${!ARR[@]}"
echo "values: ${ARR[@]}"
}
declare -A HASH
HASH=([foo]=bar [zoom]=fast)
funky HASH # notice that I'm just passing the word 'HASH' to the function
spowoduje następujące dane wyjściowe:
indexes: foo zoom
values: bar fast
Ponieważ jest to przekazywane przez odwołanie, można również przypisać tablicę w funkcji. Tak, przywoływana tablica musi mieć zasięg globalny, ale nie powinno to być zbyt duże, biorąc pod uwagę, że jest to skrypt skryptowy. Aby przekazać asocjacyjną lub rzadką tablicę indeksowaną przez wartość do funkcji, należy rzucić wszystkie indeksy i wartości na listę argumentów (nie jest to zbyt przydatne, jeśli jest to duża tablica) jako pojedyncze ciągi:
funky "${!array[*]}" "${array[*]}"
a następnie napisanie wiązki kodu wewnątrz funkcji w celu ponownego złożenia tablicy.