In einer Bourne-ähnlichen Shell, die Array-Variablen unterstützt, können wir mithilfe von Parsing prüfen, ob es sich bei der Variablen um ein Array handelt.
Alle folgenden Befehle wurden nach dem Ausführen ausgeführt a=(1 2 3)
.
zsh
:
$ declare -p a
typeset -a a
a=( 1 2 3 )
bash
:
$ declare -p a
declare -a a='([0]="1" [1]="2" [2]="3")'
ksh93
:
$ typeset -p a
typeset -a a=(1 2 3)
pdksh
und seine Ableitung:
$ typeset -p a
set -A a
typeset a[0]=1
typeset a[1]=2
typeset a[2]=3
yash
:
$ typeset -p a
a=('1' '2' '3')
typeset a
Ein Beispiel in bash
:
if declare -p var 2>/dev/null | grep -q 'declare -a'; then
echo array variable
fi
Dieser Ansatz ist zu aufwendig und muss eine Subshell erzeugen. Die Verwendung einer anderen Shell, die wie =~
in [[ ... ]]
eingebaut ist, benötigt keine Subshell, ist aber immer noch zu kompliziert.
Gibt es einen einfacheren Weg, um diese Aufgabe zu erfüllen?
Antworten:
Ich glaube nicht, dass Sie das können, und ich glaube nicht, dass es tatsächlich einen Unterschied macht.
Das macht das gleiche in einem von
ksh93
undbash
. Möglicherweise sind alle Variablen Arrays in diesen Shells oder zumindest reguläre Variablen, denen keine speziellen Attribute zugewiesen wurden, aber ich habe nicht viel davon überprüft.In diesem
bash
Handbuch wird das unterschiedliche Verhalten eines Arrays im Vergleich zu einer Zeichenfolgenvariablen bei der Verwendung von+=
Zuweisungen erläutert. Anschließend wird jedoch abgesichert und angegeben, dass sich das Array nur in einem zusammengesetzten Zuweisungskontext anders verhält .Es wird auch angegeben, dass eine Variable als Array betrachtet wird, wenn einem Index ein Wert zugewiesen wurde - und explizit die Möglichkeit einer Nullzeichenfolge einschließt. Oben sehen Sie, dass eine reguläre Zuweisung definitiv dazu führt, dass ein Index zugewiesen wird - und ich denke, dass alles ein Array ist.
In der Praxis können Sie möglicherweise Folgendes verwenden:
... um gesetzte Variablen, denen nur ein einziger Index mit dem Wert 0 zugewiesen wurde, eindeutig zu lokalisieren.
quelle
${a[1]-not array}
ich die Aufgabe erledigen kann, oder?bash
Handbuch: Eine Array-Variable wird als gesetzt betrachtet, wenn einem Index ein Wert zugewiesen wurde. Die Nullzeichenfolge ist ein gültiger Wert. Wenn ein Index zugewiesen ist, wird ihm ein Array pro Spezifikation zugewiesen. In der Praxis auch nein, weil man das kanna[5]=x
. Ich denke,[ 1 -eq "${#a[@]}" ] && [ -n "${a[0]+1}" ]
könnte funktionieren.Sie wollen also effektiv nur den mittleren Teil
declare -p
ohne den Müll drum herum?Sie könnten ein Makro schreiben wie:
damit Sie tun können:
(Eine bloße Funktion reicht nicht aus, wenn Sie dies für funktionslokale Variablen verwenden möchten.)
Mit Aliasen
quelle
alias vartype="$VARTYPE"
... oder definiere das$VARTYPE
überhaupt nicht - es sollte funktionieren, oder? Sie sollten dasshopt
Ding nur brauchen,bash
weil es mit der Spezifikation bezüglich deralias
Erweiterung von Skripten bricht .In zsh
quelle
echo ${(t)var}
ist es einfacher. Danke dafür.Um die Variable var zu testen, mit
Es ist möglich zu testen, ob es mehr als einen Array-Index gibt:
Wenn der erste Indexwert nicht Null ist:
Die einzige schwere Verwirrung ist, wenn es nur einen Indexwert gibt und dieser Wert null (oder eins) ist.
In diesem Fall ist es möglich, einen Nebeneffekt zu verwenden, bei dem versucht wird, ein Array-Element aus einer Variablen zu entfernen, die kein Array ist:
Dies funktioniert korrekt für Bash:
Für zsh muss der Index möglicherweise 1 sein (es sei denn, ein kompatibler Modus ist aktiv).
Die Unterschale wird benötigt, um den Nebeneffekt des Löschens des Index 0 von var zu vermeiden.
Ich habe keine Möglichkeit gefunden, es in ksh zum Laufen zu bringen.
Bearbeiten 1
Diese Funktion funktioniert nur in bash4.2 +
Bearbeiten 2
Dies funktioniert auch nur für bash4.2 +
Hinweis: Dies führt zu falsch positiven Ergebnissen, wenn var die getesteten Zeichenfolgen enthält.
quelle
( unset "var[0]" 2>/dev/null; ) && echo "var is an array."
korrekt gemeldet , dass var ein Array ist, wenn var aufvar=()
ein Array mit null Elementen festgelegt wurde. Es wirkt genau gleich zu deklarieren.grep -E
anstattgrep -P
die Abhängigkeit von GNU grep zu vermeiden.-a
, wie folgt aus :declare -airl var='()'
. Daher wird der grep-Test funktionieren .Bei Bash handelt es sich um einen kleinen Hack (wenn auch dokumentiert): Versuchen Sie
typeset
, das Attribut "array" zu entfernen:(Dies ist nicht möglich. Sie können
zsh
ein Array in einen Skalar konvertieren, dabash
dies ausdrücklich verboten ist.)So:
Oder in einer Funktion, die Vorbehalte am Ende beachten:
Beachten Sie die Verwendung von
typeset -g
(bash-4.2 oder höher). Dies ist in einer Funktion erforderlich, damittypeset
(syn.declare
) Nicht wielocal
der Wert funktioniert und den Sie untersuchen möchten. Dies gilt auch nicht für Funktionstypen mit "Variablen". Sie könnentypeset -f
bei Bedarf einen weiteren Verzweigungstest hinzufügen .Eine weitere (fast vollständige) Option besteht darin, Folgendes zu verwenden:
Es gibt jedoch ein kleines Problem: Ein Array mit einem einzelnen Index von 0 entspricht zwei der oben genannten Bedingungen. Dies ist etwas, worauf mikeserv auch hinweist, bash hat wirklich keine harte Unterscheidung, und einige davon (wenn Sie das Changelog überprüfen) können auf ksh und die Kompatibilität mit dem Verhalten
${name[*]}
oder${name[@]}
Verhalten auf einem Nicht-Array zurückgeführt werden.Also a Teillösung ist also:
Ich habe in der Vergangenheit eine Variation davon verwendet:
Auch das braucht eine Unterschale.
Eine weitere möglicherweise nützliche Technik ist
compgen
:Dadurch werden alle indizierten Arrays aufgelistet. Assoziative Arrays werden jedoch nicht speziell behandelt (bis zu bash-4.4) und erscheinen als reguläre Variablen (
compgen -A variable
).quelle
typeset +a
meldet auch einen Fehler in ksh. Allerdings nicht in zsh.Kurze Antwort:
Für die beiden Shells, die diese Notation (
bash
undksh93
) eingeführt haben, ist eine skalare Variable nur ein Array mit einem einzelnen Element .Für die Erstellung eines Arrays ist keine spezielle Deklaration erforderlich . Nur die Zuordnung ist ausreichend und eine einfache Zuordnung
var=value
ist identisch mitvar[0]=value
.quelle
bash -c 'unset var; var=foo; typeset -p var'
. Meldet bash answer ein Array (benötigt ein -a)? Jetzt vergleichen mit:bash -c 'unset var; var[12]=foo; typeset -p var'
. Warum gibt es einen Unterschied? A: Die Shell behält (für gut oder für schlecht) eine Vorstellung davon bei, welche Variablen Skalare oder Arrays sind. Die Shell ksh mischt beide Konzepte in einem.yashs
array
Builtin hat einige Optionen, die nur mit Array-Variablen funktionieren. Beispiel: Die-d
Option meldet einen Fehler bei Nicht-Array-Variablen:Also können wir so etwas machen:
Dieser Ansatz funktioniert nicht, wenn die Array-Variable schreibgeschützt ist . Der Versuch, eine schreibgeschützte Variable zu ändern , führt zu einem Fehler:
quelle
quelle