Czy istnieje zwięzły sposób testowania obsługi tablicy przez lokalną powłokę podobną do Bourne'a w wierszu poleceń?
Jest to zawsze możliwe:
$ arr=(0 1 2 3);if [ "${arr[2]}" != 2 ];then echo "No array support";fi
lub testowanie $SHELL
i wersja powłoki:
$ eval $(echo "$SHELL --version") | grep version
a następnie czytanie strony podręcznika, zakładając, że mam do niej dostęp. (Nawet tam, pisząc z /bin/bash
, zakładam, że wszystkie powłoki podobne do Bourne'a dopuszczają długą opcję --version
, kiedy na przykład psuje się to dla ksh .)
Szukam prostego testu, który mógłby być bezobsługowy i włączony do sekcji Użycie na początku skryptu, a nawet przed jego wywołaniem.
shell-script
shell
array
Cbhihe
źródło
źródło
csh
nie jest skorupą Bourne'a.tcsh
też nie jest jeden (jestcsh
z kilkoma naprawionymi błędami)$SHELL
jest to preferowana powłoka użytkownika, podobnie jak$EDITOR
jego preferowany edytor tekstu. Ma niewiele wspólnego z aktualnie działającą powłoką.eval
użycie wyjścia$SHELL --version
jako kodu powłoki nie ma sensu.Odpowiedzi:
Zakładając, że chcesz ograniczyć do powłokach typu bourne (wiele innych muszli jak
csh
,tcsh
,rc
,es
lubfish
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 jakksh
w większości tradycyjnych komercyjnych Unices, gdzie jest również podstawąsh
)set -A array foo bar
lubset -A array -- "$var" ...
jeśli nie możesz zagwarantować, że$var
nie rozpocznie się od znaku-
lub+
.0
.a[1]=value
.a[5]=foo
zadziała, nawet jeślia[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.${#a[@]}
to liczba przypisanych elementów w tablicy (nie największy przypisany indeks).[[ -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 czasemsh
kilka BSD i była jedyną implementacją ksh typu open source przed uwolnieniem źródła ksh93):Najczęściej jak,
ksh88
ale uwaga: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.mksh
mają kilka dodatkowych operatorów inspirowane zbash
,ksh93
lubzsh
podobne zadania laa=(x y)
,a+=(z)
,${!a[@]}
aby uzyskać listę przypisanych indeksów.zsh
.zsh
tablice są na ogół lepiej zaprojektowane i podjąć najlepszeksh
icsh
tablice. Są podobne,ksh
ale z istotnymi różnicami:ksh
emulacji), co jest zgodne z tablicą Bourne'a (parametry pozycji $ @, którazsh
również wyświetla się jako tablica $ argv) icsh
tablice.$a
nie jest tym samym co,${a[0]}
ale rozwija się do niepustych elementów tablicy ("${a[@]}"
dla wszystkich elementów jak wksh
).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.a=(x y)
.set -A a x y
działa również, aleset -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ę naksh88
) iksh
odSolaris 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ę.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}"
).a=([2]=foo [5]=bar)
składni można jednocześnie zdefiniować rzadkie tablice.zsh
, ale ogromna liczba operatorów wsparła również manipulowanie tablicami."${!a[@]}"
aby pobrać listę indeksów tablicowych.bash
.bash
jest powłoką projektu GNU. Jest używany jaksh
w najnowszych wersjach OS / X i niektórych dystrybucjach GNU / Linux.bash
tablice najczęściej emulująksh88
te z niektórymi cechamiksh93
izsh
.a=(x y)
utrzymany.set -A a x y
nie obsługiwanea=()
tworzy pustą tablicę (bez zmiennych złożonychbash
)."${!a[@]}"
dla listy indeksów.a=([foo]=bar)
Składnia obsługiwane, a także kilka innych zksh93
izsh
.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
a=(var value)
array
polecenie wbudowanearray -s a 5 value
modyfikacja piątego elementu nie powiodłaby się, gdyby ten element nie został wcześniej przypisany.${a[#]}
,${#a[@]}
jest wielkość elementów w formie listy.a=("$a")
Przed dodaniem lub modyfikacją elementów należy ponownie zdefiniować zmienną skalarną jako tablicę.sh
.Z tego wynika, że wykrywanie obsługi macierzy jest możliwe dzięki:
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ć
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 doksh
tablic w lokalnych zasięgach (w funkcjach lub funkcjach anonimowych).Możesz także emulować
ksh
(poprawić zgodność zksh
tablicami i kilkoma innymi obszarami) z:Mając to na uwadze i jesteś gotów do spadku poparcia dla
yash
aksh88
i starsze wersjepdksh
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 niea=()
)"${a[#]}"
,"${a[@]}"
,"${a[0]}"
w tych funkcjach, które mają
emulate -L ksh
, podczas gdyzsh
użytkownik nadal używa swoich tablic normalnie w sposób zsh.źródło
Możesz użyć
eval
do wypróbowania składni tablicy:źródło
ksh88
obsługuje tablice, ale nie obsługujea=()
. Wksh93
,a=()
deklaruje zmienną związek, a nie tablicy, chyba że zmienna została zadeklarowana jako tablica wcześniej.yash
nie robisz,a[5]=1
alearray -s a 5 1
ksh93
złożona mnie zaskoczyła, czy mógłbyś przekazać mi część dokumentacji na jej temat. Dodaję1
do tablicy, aby działała.