Hashtable Keys und die Groß- und Kleinschreibung
2025-01-25Ich mag hashtables, da sie sich für viele Dinge einsetzen lassen, aber bevor du sie Verwendest, solltest du darüber nachdenken wie du sie verwenden willst.
Und du solltest einige Dinge über das "Verhalten" von hashtables wissen. Eines dieser Dinge ist das Verhalten von Hashtables zu Groß- und Kleinschreibung.
Wenn du eine Hashtable erstellst:
$myHashtable = @{}
Und ein paar Key / Werte pare hinzufügst, kann es passieren, dass du ein anderes Resultat bekommst, als du erwartest:
$myHashtable.Add("Key","Value")
$myHashtable.Add("key","value2")
Hier bekommst du einen Fehler, dass der Key bereits existiert.
MethodInvocationException: Exception calling "Add" with "2" argument(s): "Item has already been added. Key in dictionary: 'Key1' Key being added: 'key1'"
Das passiert, weil die Vergleichsmethode die für die Keys verwendet wird nicht zwischen Groß- und Kleinschreibung unterscheidet.
Wenn du aber ein Hashtable erstellst, indem du New-Object verwendest, dann funktioniert das objge und du hast zwei Keys die gleich heißen. Der unterschied ist lediglich, dass der eine mit einem Großbuchstaben beginnt, und der Andere mit einem Kleinbuchstaben.
$myHashtable = New-Object hashtable
$myHashtable.Add("Key","Value")
$myHashtable.Add("key","value")
In den meisten Fällen, ist diese Verhalten nicht notwendig oder sogar unerwünscht. Doch manchmal, ist es genau dass, was du wills und brauchst.
Die Frage ist jetzt, wie kann ich ein bestimmtes Vergleichsverhalten erhalten?
Der einfachste weg ist einfach die Vergleichsmethode von der System.StringComparer
Klasse zu verwenden.
$myHashtable = New-Object hashtable([System.StringComparer]::InvariantCulture)
$myHashtable = [hashtable]::new([System.StringComparer]::InvariantCulture)
Beides mal wird ein Hashtable erstellt der Groß- und Kleinschreibung in den Keys berücksichtigt.
Um ein Hashtable zu erstellen bei dem explizit nicht zwishen Groß- und Kleinschreibung unterschieden wird verwendest du folgendes:
[System.StringComparer]::InvariantCultureIgnoreCase
Jetzt stellt sich natürlich die Frage, wofür könnte es notwendig sein beim Key zwischen Groß- und Kleinschreibung zu unterscheiden?
Ein wirklich guter Anwendungsfall ist es wenn du Hashtables mit RegEx kombinierst und es als eine Art ersetzungstabelle verwendest.
$inputString="Das ist ein test string mit allen möglichen Umlauten wie öäüÄÖÜß und auch 'text in einfachen Anführungszeichen'"
$myHashtable = New-Object hashtable([System.StringComparer]::InvariantCulture)
$MyHashtable[' ']=''
$MyHashtable['Ň']='N'
$MyHashtable['É']='E'
$MyHashtable['ē']='e'
$MyHashtable['ö']='oe'
$MyHashtable['&']=''
$MyHashtable['ň']='n'
$MyHashtable['ī']='i'
$MyHashtable['''']=''
$MyHashtable['í']='i'
$MyHashtable['Ö']='Oe'
$MyHashtable['Ā']='A'
$MyHashtable['ā']='a'
$MyHashtable['Ž']='Z'
$MyHashtable['é']='e'
$MyHashtable[',']=''
$MyHashtable['ř']='r'
$MyHashtable['ß']='ss'
$MyHashtable['Í']='I'
$MyHashtable['Ř']='R'
$MyHashtable['Ä']='Ae'
$MyHashtable['ü']='ue'
$MyHashtable['š']='s'
$MyHashtable['Č']='C'
$MyHashtable['`']=''
$MyHashtable['ž']='z'
$MyHashtable['ä']='ae'
$MyHashtable['/']=''
$MyHashtable['Ü']='Ue'
$MyHashtable['č']='c'
$MyHashtable['-']=''
# Erstelle einen RegEx ausdruk in dem Format [Zeichen die ersetzt werden] Sonderzeichen werden maskiert
$pattern = $("[" + $([regex]::Escape($( -join $MyHashtable.Keys))) + "]")
# Maskiere Zeichen die für Regex eine Bedeutung haben und von [regex]::Escape nicht maskiert werden
$pattern= $pattern -replace '-','\-'
# Verwende [regex]::Replace um jedes vokommen mit dem passenden Zeichen aus der Haschtable zu ersetzen
$returnValue = [regex]::Replace($inputString, $pattern, { $MyHashtable[$args[0].Value] })
$returnValue
Das ist nur eine Demonstration, wofür du Hashtables mit Keys, die zwischen Groß- und Kleinschreibung unterscheiden verwenden kannst.
In meinen Scripten verwende ich diese Technik in einer Funktion, der ich die Zeichen die ersetzt werden sollen sowie die Ersatzzeichen als Parameter übergebe.