test auf leeres Array?

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
Lohengrin
Beiträge: 3227
Registriert: 29.08.2004 00:01:05
Wohnort: Montsalvat

test auf leeres Array?

Beitrag von Lohengrin » 19.11.2018 19:37:43

Code: Alles auswählen

$ foo=(pi pa po)
$ unset foo[0]
$ echo ${foo[*]@A}
declare -a foo=([1]="pa" [2]="po")
$ [[ -v foo ]] ; echo $?
1
8O foo gibt es doch. Ist ein Array. foo[0] gibt es nicht. Aber ich habe doch nach foo gefragt.

Code: Alles auswählen

$ bar=pipapo
$ echo ${bar[*]@A}
bar='pipapo'
$ [[ -v bar[0] ]] ; echo $?
0
8O bar[0] gibt es nicht. bar ist kein Array.

Code: Alles auswählen

$ foo=
$ [[ -v foo ]] ; echo $?
0
set und null. ok.

Code: Alles auswählen

$ bar=()
$ [[ -v bar ]] ; echo $?
1
8O
Wie testet man auf ein leeres Array?
Harry, hol schon mal das Rasiermesser!

owl102

Re: test auf leeres Array?

Beitrag von owl102 » 19.11.2018 19:48:01

Lohengrin hat geschrieben: ↑ zum Beitrag ↑
19.11.2018 19:37:43
8O foo gibt es doch. Ist ein Array. foo[0] gibt es nicht. Aber ich habe doch nach foo gefragt.
"foo" wird bei Arrays als "foo[0]" ausgewertet. Also völlig normal.

Siehe auch http://mywiki.wooledge.org/BashFAQ/005 :
http://mywiki.wooledge.org/BashFAQ/005 hat geschrieben: "$a" -- Same as "${a[0]}". Does NOT expand to the entire array. This usage is considered confusing at best, but is usually a bug.
Wie testet man auf ein leeres Array?
Zum Beispiel mit

Code: Alles auswählen

(( ${#foo[*]} == 0 ))

Code: Alles auswählen

$ foo=( a b )
$ (( ${#foo[*]} == 0 ))
$ echo $?
1
$ foo=()
$ (( ${#foo[*]} == 0 ))
$ echo $?
0

Benutzeravatar
Lohengrin
Beiträge: 3227
Registriert: 29.08.2004 00:01:05
Wohnort: Montsalvat

Re: test auf leeres Array?

Beitrag von Lohengrin » 19.11.2018 19:56:38

owl102 hat geschrieben: ↑ zum Beitrag ↑
19.11.2018 19:48:01
Lohengrin hat geschrieben: ↑ zum Beitrag ↑
19.11.2018 19:37:43
8O foo gibt es doch. Ist ein Array. foo[0] gibt es nicht. Aber ich habe doch nach foo gefragt.
"foo" wird bei Arrays als "foo[0]" ausgewertet. Also völlig normal.
Finde ich nicht normal. Das hat für mich unerwartete Effekte.
owl102 hat geschrieben: ↑ zum Beitrag ↑
19.11.2018 19:48:01
Wie testet man auf ein leeres Array?
Zum Beispiel mit

Code: Alles auswählen

(( ${#foo[*]} == 0 ))
Das unterscheidet nicht zwischen leerem Array, null oder unset.
null kann ich mit -v fangen. Aber leeres Array?
Harry, hol schon mal das Rasiermesser!

Benutzeravatar
Lohengrin
Beiträge: 3227
Registriert: 29.08.2004 00:01:05
Wohnort: Montsalvat

Re: test auf leeres Array?

Beitrag von Lohengrin » 20.11.2018 01:55:28

Mit unset foo wird, wenn foo ein Array ist, das Array entfernt. Aber [[ -v foo ]] bezieht sich auf foo[0]. Das passt mMn nicht zusammen.
Wenn foo ein Array ist, dann wird mit foo= das foo[0] auf null gesetzt, und wenn foo kein Array ist, dann wird mit foo= das ganze foo auf null gesetzt. Um sicher zu sein, dass das ganze foo auf null ist, muss man unset foo ; foo= machen.

[[ ${#foo[*]} == 0 ]] sagt mir, dass foo ein leeres Array ist, foo leer ist, oder foo unset ist. Aber declare -p foo hat Rückgabewert 0, wenn foo ein leeres Array ist. Leider kann man mit declare foo auch foo deklarieren, ohne es zu setzen.
Damit habe ich schon fast einen Test auf leeres Array gefunden, nämlich declare -p foo &>/dev/null && [ ${#foo[0]} == 0 ]. Aber eben nur fast, weil das noch ein deklariertes und ungesetztes foo mitnimmt.
Die Frage bleibt. Wie testet man auf leeres Array?

Es ist ja nicht nur so, dass bei einem Array ${foo} das ${foo[0]} ist. Auch umgekehrt ist bei einem Nichtarray ${foo[0]} das ${foo}. Aber bei ${foo[-1]} dann doch nicht, gibt Fehlermeldung.

Gibt es einen guten Grund für dieses Verhalten? Ich sehe keinen, bin dafür, dass das abgeschafft wird.
Harry, hol schon mal das Rasiermesser!

Antworten