Zakładając, że chcesz ograniczyć do powłokach typu bourne (wiele innych muszli jak csh
, tcsh
, rc
, es
lub fish
tablic wsparcia ale pisząc scenariusz zgodny jednocześnie do Bourne-jak muszle i tych jest trudne i na ogół pozbawione sensu, ponieważ są one tłumaczy na zupełnie inny i niekompatybilne języki), zauważ, że istnieją znaczące różnice między implementacjami.
Powłoki typu Bourne'a obsługujące tablice to:
ksh88
(to pierwsza implementująca tablice, ksh88 jest nadal spotykany jak ksh
w większości tradycyjnych komercyjnych Unices, gdzie jest również podstawą sh
)
- tablice są jednowymiarowe
- Tablice są zdefiniowane jako
set -A array foo bar
lub set -A array -- "$var" ...
jeśli nie możesz zagwarantować, że $var
nie rozpocznie się od znaku -
lub +
.
- Indeksy tablic zaczynają się od
0
.
- Poszczególne elementy tablicy są przypisywane jako
a[1]=value
.
- tablice są rzadkie. To
a[5]=foo
zadziała, nawet jeśli a[0,1,2,3,4]
nie są ustawione i pozostawi je rozbrojone.
${a[5]}
aby uzyskać dostęp do elementu indeksu 5 (niekoniecznie szóstego elementu, jeśli tablica jest rzadka). 5
Nie może być dowolne wyrażenie arytmetyczne.
- Rozmiar tablicy i indeks dolny są ograniczone (do 4096).
${#a[@]}
to liczba przypisanych elementów w tablicy (nie największy przypisany indeks).
- nie ma możliwości poznania listy przypisanych indeksów dolnych (oprócz testowania 4096 elementów indywidualnie
[[ -n "${a[i]+set}" ]]
).
$a
jest taki sam jak ${a[0]}
. To znaczy, że tablice w jakiś sposób rozszerzają zmienne skalarne, nadając im dodatkowe wartości.
pdksh
i pochodne (to podstawa, ksh
a czasem sh
kilka BSD i była jedyną implementacją ksh typu open source przed uwolnieniem źródła ksh93):
Najczęściej jak, ksh88
ale uwaga:
- Niektóre stare implementacje nie obsługiwały
set -A array -- foo bar
( --
nie były tam potrzebne).
${#a[@]}
to jeden plus wskaźnik największej przypisanej wartości. ( a[1000]=1; echo "${#a[@]}"
wyprowadza 1001, mimo że tablica ma tylko jeden element.
- w nowszych wersjach rozmiar tablicy nie jest już ograniczony (inny niż rozmiar liczb całkowitych).
- Nowsze wersje
mksh
mają kilka dodatkowych operatorów inspirowane z bash
, ksh93
lub zsh
podobne zadania la a=(x y)
, a+=(z)
, ${!a[@]}
aby uzyskać listę przypisanych indeksów.
zsh
. zsh
tablice są na ogół lepiej zaprojektowane i podjąć najlepsze ksh
i csh
tablice. Są podobne, ksh
ale z istotnymi różnicami:
- indeksy zaczynają się od 1, a nie od 0 (z wyjątkiem
ksh
emulacji), co jest zgodne z tablicą Bourne'a (parametry pozycji $ @, która zsh
również wyświetla się jako tablica $ argv) i csh
tablice.
- są one odrębnym typem od zmiennych normalnych / skalarnych. Operatorzy stosują się do nich inaczej i tak, jak zwykle można się spodziewać.
$a
nie jest tym samym co, ${a[0]}
ale rozwija się do niepustych elementów tablicy ( "${a[@]}"
dla wszystkich elementów jak w ksh
).
- są to normalne tablice, a nie rzadkie tablice.
a[5]=1
działa, ale przypisuje wszystkie elementy od 1 do 4 pusty ciąg, jeśli nie zostały one przypisane. Tak więc ${#a[@]}
(to samo ${#a}
co w ksh jest wielkością elementu indeksu 0) jest liczba elementów w tablicy i największy przypisany indeks.
- obsługiwane są tablice asocjacyjne.
- obsługiwana jest duża liczba operatorów do pracy z tablicami, zbyt duża, aby ją tutaj wymienić.
- tablice zdefiniowane jako
a=(x y)
. set -A a x y
działa również, ale set -A a -- x y
nie jest obsługiwane, chyba że w emulacji ksh ( --
nie jest potrzebne w emulacji zsh).
ksh93
. (tutaj opisujące najnowsze wersje). ksh93
, od dawna uważany za eksperymentalny można teraz znaleźć w coraz większej liczbie systemów, odkąd został wydany jako FOSS. Na przykład, jest to /bin/sh
(gdzie zastąpiła Bourne Shell /usr/xpg4/bin/sh
, POSIX powłoki nadal opiera się na ksh88
) i ksh
od Solaris 11
. Jego tablice rozszerzają i poprawiają ksh88.
a=(x y)
może być użyty do zdefiniowania tablicy, ale ponieważ a=(...)
jest również używany do zdefiniowania zmiennych złożonych ( a=(foo=bar bar=baz)
), a=()
jest niejednoznaczny i deklaruje zmienną złożoną, a nie tablicę.
- tablice są wielowymiarowe (
a=((0 1) (0 2))
), a elementy tablicy mogą być również zmiennymi złożonymi ( a=((a b) (c=d d=f)); echo "${a[1].c}"
).
- Za pomocą
a=([2]=foo [5]=bar)
składni można jednocześnie zdefiniować rzadkie tablice.
- Zniesiono ograniczenia wielkości.
- Nie w stopniu
zsh
, ale ogromna liczba operatorów wsparła również manipulowanie tablicami.
"${!a[@]}"
aby pobrać listę indeksów tablicowych.
- tablice asocjacyjne obsługiwane również jako osobny typ.
bash
. bash
jest powłoką projektu GNU. Jest używany jak sh
w najnowszych wersjach OS / X i niektórych dystrybucjach GNU / Linux. bash
tablice najczęściej emulują ksh88
te z niektórymi cechami ksh93
i zsh
.
a=(x y)
utrzymany. set -A a x y
nie obsługiwane a=()
tworzy pustą tablicę (bez zmiennych złożonych bash
).
"${!a[@]}"
dla listy indeksów.
a=([foo]=bar)
Składnia obsługiwane, a także kilka innych z ksh93
i zsh
.
- najnowsze
bash
wersje obsługują również tablice asocjacyjne jako osobny typ.
yash
. Jest to stosunkowo nowa, czysta, wielobajtowa implementacja sh POSIX. Nie w powszechnym użyciu. Jego tablice są kolejnym czystym API podobnym dozsh
- tablice nie są rzadkie
- Indeksy tablic zaczynają się od 1
- zdefiniowane (i zadeklarowane) za pomocą
a=(var value)
- Elementy wkładane, usuwane lub modyfikowane przy
array
polecenie wbudowane
array -s a 5 value
modyfikacja piątego elementu nie powiodłaby się, gdyby ten element nie został wcześniej przypisany.
- liczba elementów w matrycy
${a[#]}
, ${#a[@]}
jest wielkość elementów w formie listy.
- tablice są osobnym typem.
a=("$a")
Przed dodaniem lub modyfikacją elementów należy ponownie zdefiniować zmienną skalarną jako tablicę.
- tablice nie są obsługiwane po wywołaniu jako
sh
.
Z tego wynika, że wykrywanie obsługi macierzy jest możliwe dzięki:
if (unset a; set -A a a; eval "a=(a b)"; eval '[ -n "${a[1]}" ]'
) > /dev/null 2>&1
then
array_supported=true
else
array_supported=false
fi
nie wystarczy, aby móc korzystać z tych tablic. Musisz zdefiniować polecenia otoki, aby przypisać tablice jako całość i poszczególne elementy, i upewnij się, że nie próbujesz tworzyć rzadkich tablic.
Lubić
unset a
array_elements() { eval "REPLY=\"\${#$1[@]}\""; }
if (set -A a -- a) 2> /dev/null; then
set -A a -- a b
case ${a[0]}${a[1]} in
--) set_array() { eval "shift; set -A $1"' "$@"'; }
set_array_element() { eval "$1[1+(\$2)]=\$3"; }
first_indice=0;;
a) set_array() { eval "shift; set -A $1"' -- "$@"'; }
set_array_element() { eval "$1[1+(\$2)]=\$3"; }
first_indice=1;;
--a) set_array() { eval "shift; set -A $1"' "$@"'; }
set_array_element() { eval "$1[\$2]=\$3"; }
first_indice=0;;
ab) set_array() { eval "shift; set -A $1"' -- "$@"'; }
set_array_element() { eval "$1[\$2]=\$3"; }
first_indice=0;;
esac
elif (eval 'a[5]=x') 2> /dev/null; then
set_array() { eval "shift; $1=("'"$@")'; }
set_array_element() { eval "$1[\$2]=\$3"; }
first_indice=0
elif (eval 'a=(x) && array -s a 1 y && [ "${a[1]}" = y ]') 2> /dev/null; then
set_array() { eval "shift; $1=("'"$@")'; }
set_array_element() {
eval "
$1=(\${$1+\"\${$1[@]}"'"})
while [ "$(($2))" -ge "${'"$1"'[#]}" ]; do
array -i "$1" "$2" ""
done'
array -s -- "$1" "$((1+$2))" "$3"
}
array_elements() { eval "REPLY=\${$1[#]}"; }
first_indice=1
else
echo >&2 "Array not supported"
fi
A następnie uzyskać dostęp do elementów tablicy z "${a[$first_indice+n]}"
cała lista ze "${a[@]}"
i korzystać z funkcji otoki ( array_elements
, set_array
, set_array_element
), aby uzyskać liczbę elementów tablicy (w $REPLY
), ustawić tablicę jako całość lub przypisać poszczególnych elementów.
Prawdopodobnie nie warte wysiłku. Użyję perl
lub ograniczenie do tablicy powłoki Bourne'a / POSIX: "$@"
.
Jeśli intencją jest, aby jakiś plik był pozyskiwany przez interaktywną powłokę użytkownika w celu zdefiniowania funkcji, które wewnętrznie korzystają z tablic, oto kilka dodatkowych uwag, które mogą być przydatne.
Można skonfigurować zsh
tablice, aby były bardziej podobne do ksh
tablic w lokalnych zasięgach (w funkcjach lub funkcjach anonimowych).
myfunction() {
[ -z "$ZSH_VERSION" ] || setopt localoption ksharrays
# use arrays of indice 0 in this function
}
Możesz także emulować ksh
(poprawić zgodność z ksh
tablicami i kilkoma innymi obszarami) z:
myfunction() {
[ -z "$ZSH_VERSION" ] || emulate -L ksh
# ksh code more likely to work here
}
Mając to na uwadze i jesteś gotów do spadku poparcia dla yash
a ksh88
i starsze wersje pdksh
pochodne, i tak długo, jak nie próbować tworzyć macierze rzadkie, należy być w stanie konsekwentnie używać:
a[0]=foo
a=(foo bar)
(ale nie a=()
)
"${a[#]}"
, "${a[@]}"
,"${a[0]}"
w tych funkcjach, które mają emulate -L ksh
, podczas gdy zsh
użytkownik nadal używa swoich tablic normalnie w sposób zsh.