Angenommen , Sie zu Bourne-wie Muscheln einschränken wollen (viele andere Muscheln mögen csh
, tcsh
, rc
, es
oder fish
Support - 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 ksh
auf 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 bar
oder set -A array -- "$var" ...
wenn Sie nicht garantieren können, dass dies $var
nicht 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]=foo
funktioniert 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 5
kann 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}" ]]
).
$a
ist das gleiche wie ${a[0]}
. Das heißt, Arrays erweitern irgendwie skalare Variablen, indem sie ihnen zusätzliche Werte geben.
pdksh
und Derivate (das ist die Basis für die ksh
und manchmal sh
für mehrere BSDs und war die einzige OpenSource-Implementierung von ksh, bevor die Quelle ksh93 freigegeben wurde):
Meistens wie ksh88
aber 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
mksh
haben ein paar zusätzlichen Betreiber von inspiriert bash
, ksh93
oder zsh
wie Zuweisungen a la a=(x y)
, a+=(z)
, ${!a[@]}
die Liste des zugewiesenen Indizes zu erhalten.
zsh
. zsh
Arrays sind im Allgemeinen besser gestaltet und nutzen das Beste aus ksh
und csh
Arrays. Sie sind ähnlich, ksh
aber mit signifikanten Unterschieden:
- Indizes beginnen bei 1, nicht bei 0 (außer bei der
ksh
Emulation), was mit dem Bourne-Array (den Positionsparametern $ @, das zsh
auch als $ argv-Array verfügbar gemacht wird) und den csh
Arrays übereinstimmt .
- Sie sind ein separater Typ von normalen / skalaren Variablen. Operatoren gelten für sie anders und wie Sie es allgemein erwarten würden.
$a
ist 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]=1
funktioniert, 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 y
funktioniert auch, wird aber set -A a -- x y
nur in der ksh-Emulation unterstützt (dies --
wird in der zsh-Emulation nicht benötigt).
ksh93
. (Hier werden die neuesten Versionen beschrieben). ksh93
Das 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 ksh
von 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
. bash
ist die Hülle des GNU-Projekts. Es wird wie sh
in neueren Versionen von OS / X und einigen GNU / Linux-Distributionen verwendet. bash
Arrays emulieren meistens ksh88
solche mit einigen Merkmalen von ksh93
und 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 ksh93
und zsh
.
- Neuere
bash
Versionen 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
array
eingebauten
array -s a 5 value
die 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 perl
das 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 zsh
Arrays so konfigurieren , dass sie ksh
Arrays 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 ksh
Arrays 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 yash
und ksh88
ältere Versionen von pdksh
Derivaten 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 zsh
Benutzer seine Arrays normalerweise noch auf zsh-Weise benutzt.