Angenommen , Sie zu Bourne-wie Muscheln einschränken wollen (viele andere Muscheln mögen csh, tcsh, rc, esoder fishSupport - Arrays aber ein Skript kompatibel zur gleichen Zeit zu Bourne artigen Schalen zu schreiben und das ist heikel und in der Regel sinnlos , da sie Dolmetscher sind für ganz anderen und Inkompatible Sprachen). Beachten Sie, dass zwischen den Implementierungen erhebliche Unterschiede bestehen.
Die Bourne-ähnlichen Shells, die Arrays unterstützen, sind:
ksh88(Dies ist das erste, das Arrays implementiert. Ksh88 ist immer noch kshauf den meisten herkömmlichen kommerziellen Unices zu finden, für die es auch die Basis ist. sh)
- Arrays sind eindimensional
- Arrays sind definiert als
set -A array foo baroder set -A array -- "$var" ...wenn Sie nicht garantieren können, dass dies $varnicht mit einem -oder beginnt +.
- Array-Indizes beginnen bei
0.
- Einzelne Array-Elemente werden als zugewiesen
a[1]=value.
- Arrays sind spärlich. Das
a[5]=foofunktioniert auch, wenn sie a[0,1,2,3,4]nicht eingestellt sind, und lässt sie nicht gesetzt.
${a[5]}um auf das Element von Index 5 zuzugreifen (nicht unbedingt das 6. Element, wenn das Array dünn ist). Das 5kann jeder arithmetische Ausdruck sein.
- Arraygröße und Index sind begrenzt (auf 4096).
${#a[@]} ist die Anzahl der zugewiesenen Elemente im Array (nicht der größte zugewiesene Index).
- Es gibt keine Möglichkeit, die Liste der zugewiesenen Indizes zu kennen (außer die 4096-Elemente einzeln mit zu testen
[[ -n "${a[i]+set}" ]]).
$aist das gleiche wie ${a[0]}. Das heißt, Arrays erweitern irgendwie skalare Variablen, indem sie ihnen zusätzliche Werte geben.
pdkshund Derivate (das ist die Basis für die kshund manchmal shfür mehrere BSDs und war die einzige OpenSource-Implementierung von ksh, bevor die Quelle ksh93 freigegeben wurde):
Meistens wie ksh88aber beachten Sie:
- Einige alte Implementierungen wurden nicht unterstützt
set -A array -- foo bar(die wurden --dort nicht benötigt).
${#a[@]}ist eins plus der Index des größten zugewiesenen Index. ( a[1000]=1; echo "${#a[@]}"gibt 1001 aus, obwohl das Array nur ein Element enthält.
- In neueren Versionen ist die Arraygröße nicht mehr begrenzt (außer durch die Größe von Ganzzahlen).
- neuere Versionen von
mkshhaben ein paar zusätzlichen Betreiber von inspiriert bash, ksh93oder zshwie Zuweisungen a la a=(x y), a+=(z), ${!a[@]}die Liste des zugewiesenen Indizes zu erhalten.
zsh. zshArrays sind im Allgemeinen besser gestaltet und nutzen das Beste aus kshund cshArrays. Sie sind ähnlich, kshaber mit signifikanten Unterschieden:
- Indizes beginnen bei 1, nicht bei 0 (außer bei der
kshEmulation), was mit dem Bourne-Array (den Positionsparametern $ @, das zshauch als $ argv-Array verfügbar gemacht wird) und den cshArrays übereinstimmt .
- Sie sind ein separater Typ von normalen / skalaren Variablen. Operatoren gelten für sie anders und wie Sie es allgemein erwarten würden.
$aist nicht dasselbe wie, ${a[0]}sondern erweitert sich auf die nicht leeren Elemente des Arrays ( "${a[@]}"für alle Elemente wie in ksh).
- Sie sind normale Arrays, keine spärlichen Arrays.
a[5]=1funktioniert, weist aber allen Elementen von 1 bis 4 die leere Zeichenfolge zu, wenn sie nicht zugewiesen wurden. Also ${#a[@]}(genau wie ${#a}in ksh die Größe des Elements des Index 0) ist die Anzahl der Elemente im Array und der größte zugewiesene Index.
- assoziative Arrays werden unterstützt.
- Eine große Anzahl von Operatoren für die Arbeit mit Arrays wird unterstützt, zu groß, um sie hier aufzulisten.
- Arrays definiert als
a=(x y). set -A a x yfunktioniert auch, wird aber set -A a -- x ynur in der ksh-Emulation unterstützt (dies --wird in der zsh-Emulation nicht benötigt).
ksh93. (Hier werden die neuesten Versionen beschrieben). ksh93Das seit langem als experimentell angesehene Experiment findet sich nun in immer mehr Systemen, nachdem es als FOSS veröffentlicht wurde. Zum Beispiel ist es das /bin/sh(wo es die Bourne-Shell ersetzt hat /usr/xpg4/bin/sh, auf der die POSIX-Shell noch basiert ksh88) und kshvon Solaris 11. Seine Arrays erweitern und verbessern ksh88.
a=(x y)kann verwendet werden, um ein Array zu definieren, aber da a=(...)es auch zum Definieren von zusammengesetzten Variablen ( a=(foo=bar bar=baz)) verwendet wird, a=()ist es mehrdeutig und deklariert eine zusammengesetzte Variable, kein Array.
- Arrays sind mehrdimensional (
a=((0 1) (0 2))) und Array-Elemente können auch zusammengesetzte Variablen ( a=((a b) (c=d d=f)); echo "${a[1].c}") sein.
- Eine
a=([2]=foo [5]=bar)Syntax kann verwendet werden, um dünn besetzte Arrays gleichzeitig zu definieren.
- Größenbeschränkungen aufgehoben.
- Nicht im Umfang
zsh, aber eine große Anzahl von Operatoren wird auch unterstützt, um Arrays zu manipulieren.
"${!a[@]}" um die Liste der Array-Indizes abzurufen.
- assoziative Arrays werden auch als separater Typ unterstützt.
bash. bashist die Hülle des GNU-Projekts. Es wird wie shin neueren Versionen von OS / X und einigen GNU / Linux-Distributionen verwendet. bashArrays emulieren meistens ksh88solche mit einigen Merkmalen von ksh93und zsh.
a=(x y)unterstützt. set -A a x y nicht unterstützt. a=()Erstellt ein leeres Array (keine zusammengesetzten Variablen in bash).
"${!a[@]}" für die Liste der Indizes.
a=([foo]=bar)Syntax unterstützt sowie einige andere von ksh93und zsh.
- Neuere
bashVersionen unterstützen auch assoziative Arrays als separaten Typ.
yash. Es ist eine relativ neue, saubere, Multi-Byte-fähige POSIX sh-Implementierung. Nicht weit verbreitet. Seine Arrays sind eine weitere saubere API ähnlichzsh
- Arrays sind nicht spärlich
- Array-Indizes beginnen bei 1
- definiert (und deklariert) mit
a=(var value)
- Elemente eingefügt, gelöscht oder geändert mit dem
arrayeingebauten
array -s a 5 valuedie 5 zu ändern ten Element würde fehlschlagen , wenn das Element nicht vorher zugewiesen wurde.
- die Anzahl der Elemente in dem Array ist
${a[#]}, ${#a[@]}als eine Liste der Größe der Elemente zu sein.
- Arrays sind ein separater Typ. Sie müssen
a=("$a")eine skalare Variable als Array neu definieren, bevor Sie Elemente hinzufügen oder ändern können.
- Arrays werden beim Aufrufen als nicht unterstützt
sh.
Daraus können Sie die Erkennung der Array-Unterstützung ersehen, mit der Sie Folgendes tun können:
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
reicht nicht aus, um diese Arrays verwenden zu können. Sie müssen Wrapper-Befehle definieren, um Arrays als Ganzes und einzelne Elemente zuzuweisen, und sicherstellen, dass Sie nicht versuchen, spärliche Arrays zu erstellen.
Mögen
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
Und dann greifen Sie auf Array - Elemente mit "${a[$first_indice+n]}", die ganze Liste mit "${a[@]}"und verwenden Sie die Wrapper - Funktionen ( array_elements, set_array, set_array_element) die Anzahl der Elemente eines Arrays zu erhalten (in $REPLY), setzen Sie das Array als Ganzes oder assign einzelnen Elemente.
Wahrscheinlich nicht die Mühe wert. Ich würde perldas Bourne / POSIX-Shell-Array verwenden oder darauf beschränken : "$@".
Wenn die Absicht besteht, dass eine Datei von der interaktiven Shell eines Benutzers bezogen wird, um Funktionen zu definieren, die intern Arrays verwenden, finden Sie hier einige weitere nützliche Hinweise.
Sie können zshArrays so konfigurieren , dass sie kshArrays in lokalen Bereichen (in Funktionen oder anonymen Funktionen) ähneln.
myfunction() {
[ -z "$ZSH_VERSION" ] || setopt localoption ksharrays
# use arrays of indice 0 in this function
}
Sie können auch emulieren ksh(die Kompatibilität mit kshArrays und mehreren anderen Bereichen verbessern ) mit:
myfunction() {
[ -z "$ZSH_VERSION" ] || emulate -L ksh
# ksh code more likely to work here
}
In diesem Sinne und Sie sind bereit, die Unterstützung für yashund ksh88ältere Versionen von pdkshDerivaten einzustellen. Solange Sie nicht versuchen, spärliche Arrays zu erstellen, sollten Sie in der Lage sein, konsequent Folgendes zu verwenden:
a[0]=foo
a=(foo bar)(aber nicht a=())
"${a[#]}", "${a[@]}","${a[0]}"
in jenen Funktionen, die das haben emulate -L ksh, während der zshBenutzer seine Arrays normalerweise noch auf zsh-Weise benutzt.