PowerShell und Arrays

Oft muss man sich zwischen Arrays und Hashtables entscheiden. Eine Hashtable bietet natürlich einen schnellen direkten Zugriff auf ein individuelles Element, wenn man den "Key" dazu nutzt. Dieser muss dann aber auch eindeutig sein. Ein Arrays ist eine Liste, in der Elemente auch mehrfach vorkommen können. Sobald ein Array dann zweidimensional ist, entspricht es eher einer Tabelle.

Das einfache Array

Ein einfaches "Array" mit Werten ist aber relativ unspektakulär. Hier definiere ich eine Variable und belege sie gleich

PS C:\> [int[]]$table
PS C:\> $table=1,2,3,4
PS C:\> $table
1
2
3
4

Es geht natürlich auch in einer Zeile

[int[]] $table1 = 1,2,3,4,5,6,7,8,9

Ein Array kann aber auch durch den Kurzcode "@()" erstellt werden.

$status = @("OK","WARN","ERROR","FAIL",0)

Dabei muss nicht mal der Typ identisch sein

PS C:\> 0..4 | %{$status[$_].gettype()}

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object
True     True     String                                   System.Object
True     True     String                                   System.Object
True     True     String                                   System.Object
True     True     Int32                                    System.ValueType

Das müssen Sie natürlich bei der weiteren Betrachtung berücksichtigen.

Eine Tabelle als Array

Interessant wird ein Array, wenn jede Zeile selbst ein PSObject darstellt und man diese einfach aneinander ketten kann:

[array]$result=@()
$result+= [pscustomobject][ordered]@{Vorname = "Frank"; Nachname = "Carius"}
$result+= [pscustomobject][ordered]@{Vorname = "Uwe"; Nachname = "Ulbrich"}
$result

Vorname   Nachname
-------   --------
Frank     Carius
Uwe       Ulbrich

So schnell kann man dann eine Liste aufbauen, die mit Export-CSV etc. Natürlich auch sehr einfach ausgegeben und weiter verarbeitet werden kann. Einträge können hier im Gegensatz zur Hashtable auch mehrfach erscheinen. Allerdings ist ein Array in der Regel "Statisch", wie man mit einer Abfrage auch sehen kann.

$result.isfixedsize
true

Ein Zugriff mit der ADD oder REMOVE-Methode funktioniert nicht. Irritierend kann aber sein, dass ein Erweitern mit "+=" dennoch möglich ist. So ganz konsistent ist das nicht.

Beim Export-CSV werden die Feldnamen des ersten Eintrags als Tabellenüberschrift genutzt.

Arraylist

Microsoft rät mittlerweile davon ab, die Klasse "Arraylist" zu nutzen
https://docs.microsoft.com/en-us/dotnet/api/system.collections.arraylist?redirectedfrom=MSDN&view=netframework-4.8#remarks
https://stackoverflow.com/questions/2309694/arraylist-vs-list-in-c-sharp
Besser ist nur Nutzung der generischen Listen "[generic.list]"

Eine Erweiterung von Arrays ist eine Arrayliste. Manchmal stört bei einem Arrays, dass es eine statisch Größe hat und nicht einfach erweitert werden kann. Dann kann so eine Liste eine Lösung sein. Hier kann dann auch mit ADD und REMOVE gearbeitet werden.

PS C:\> [System.Collections.ArrayList]$ArrayList=@()
PS C:\> $ArrayList.GetType()

IsPublic IsSerial Name      BaseType
-------- -------- ----      --------
True     True     ArrayList System.Object

PS C:\> $ArrayList.add("Frank")
0
PS C:\> $ArrayList.add("Carsten")
1
PS C:\> $ArrayList
Frank
Carsten
PS C:\> $ArrayList.remove("Otto")

Beim "Add" wird als Rückgabe die aktuell Größe ausgegeben. Ein Remove eines nicht vorhandenen Elements liefert keine Fehlermeldung. Es ist auch nicht vorgeschrieben, dass die Elemente der Liste vom gleichen Typ sind. Das kann schon "verwirren", wie das folgende Beispiel zeigt, indem ich ein "Array" als drittes Element addiere

PS C:\> $ArrayList.add((1,2))
2
PS C:\> $ArrayList
Frank
Carsten
1
2
PS C:\> $ArrayList.Count
3

Bei der Ausgabe sieht es aus, also ob hier vier Elemente drin sind. Real sind es aber nur drei, bei der Powershell das dritte Element entsprechend ausgibt. Wer aber Element für Element durchläuft, bekommt die Information schon einzeln

PS C:\> $ArrayList[2]
1
2

Arrays in Funktionen

Etwas Vorsicht ist bei der Verwendung von Arrays als Rückgabe von Funktionen zu beachten. Der folgende Beispielcode soll das demonstrieren.

#Test-Arrayresult

function get-array{

   # Lere einfaches Array an
   $myarray=@(1,"eins",2)
   write-host "Typ1 = $($result.gettype())"
   0..2 | %{write-host $myarray[$_].gettype()}
   $myarray
}

$ergebnis=get-array
write-host "Typ2 = $($ergebnis.gettype())"
0..2 | %{$ergebnis[$_].gettype()}

Beim Aufruf ist sichtbar, dass in der Funktion noch ein Array vorhanden ist aber das aufrufende Programm ein Array von System.Object

Der Inhalt ist dann wieder die "Objket-Version" des Basetype

Weitere Links