none
foreach-object und hash tables RRS feed

  • Frage

  • Hallo,

    ich möchte eine Art INI-File einlesen welches im Prinzip Variablen enthält. Diese sind aber leider nicht alle UNIQUE (MSCS & Diskname).

    Ein Auszug aus dem INI-File der das Problem deutlich machen soll:

    ############ SNIP ##############

    # make sure this ip belongs to srm-clus-db
    IP_ADDRESS=192.168.2.10
    IP_SUBNET=255.255.248.0
    #IP_NETWORK=AAA.AERO
    IP_NETWORK=Cluster Network 2
    NETNAME_NAME = DBNetNameSRP
    # make sure this host has ip 192.168.2.10
    NETNAME_VALUE = srm-clus-db
    NETNAME_DEPENDENCY = DBIPSRP
    DISK_NAME = Cluster Disk 2
    DISK_NAME = Cluster Disk 3
    DISK_NAME = Cluster Disk 4
    DISK_NAME = Cluster Disk 5

    ############ SNIP ##############

    Bislang lese ich den Inhalt wie folgt ein um hinterher jeden Wert in eine eigene Variable einlesen zu können:

    Get-Content "$INIFILEPATH" | foreach-object -begin {$myMSCS=@{}} -process { $k = [regex]::split($_,'='); if(($k[0].CompareTo("") -ne 0) -and ($k[0].StartsWith("[") -ne $True) -and ($k[0].StartsWith("#") -ne $True)) { $myMSCS.Add($k[0].Trim(), $k[1].Trim()) } }

    Das Produziert mir auch eine wunderschöne Hash Tabelle...Leider wird dabei aber DISK_NAME immer wieder überschrieben und ich hab letztendlich immer nur einen Wert in der Hash Table -.-

    Meine Idee ist nun das ich an erster Stelle in der Hash Table eine fortlaufende ID schreibe und DISK_NAME somit ein duplicate key sein darf ... Nur wie mach ich das innerhalb der einen Anweisung?

    Oder gibt es noch eine elegantere Lösung die ich nicht sehe?

    Vielen Dank im Voraus!

    Donnerstag, 20. September 2012 11:41

Antworten

  • Mit einem Hashtable geht das so nicht, da du nur 2 Felder zur Verfügung hast (Key und Value).

     

    Das ganze lässt sich aber mit einem Array aus Objekten machen:
     

    Get-Content "$INIFILEPATH" | foreach-object -begin {
    	$myMSCS=@() ; $id = 0} -process { $k = [regex]::split($_,'='); $id++
    	if(($k[0].CompareTo("") -ne 0) -and ($k[0].StartsWith("[") -ne $True) -and ($k[0].StartsWith("#") -ne $True)) {
    
    			$obj = New-Object PSobject -Property @{
    				ID = $id
    				Name = $k[0].Trim()
    				Value = $k[1].Trim()			
    			}
    			$myMSCS += $obj
    		}		
    	}
    	
    $myMSCS | ft -AutoSize
     

    Vom Gefühl her würde ich sagen das ist eigentlich etwas Overkill, aber da du nicht erwähnt hast was du genau mit den Daten machen willst, ist dies der Weg um das von dir beschriebene Ergebnis zu erreichen.

    Grüße, Denniver

     


    Blog: http://bytecookie.wordpress.com

    Hilf mit und markiere hilfreiche Beiträge als "Hilfreich" und Beiträge die deine Frage ganz oder teilweise beantwortet haben als "Antwort".

    Donnerstag, 20. September 2012 14:09
    Moderator
  • So, ich glaube ich hab meine Lösung gefunden. Mag sein das es eleganter geht, aber für meine Laienhaften Powershell Kenntnisse finde ich das mal gar nicht schlecht:

    Get-Content "$INIFILEPATH" | foreach-object -begin {$myMSCS=@{};$id=0} -process { $k = [regex]::split($_,'=');$id++; if(($k[0].CompareTo("") -ne 0) -and ($k[0].StartsWith("[") -ne $True) -and ($k[0].StartsWith("#") -ne $True)) { $name = $k[0].Trim() $value = $k[1].Trim() if ($name.CompareTo("DISK_NAME") -eq 0){ $dname="$name$id" $k[0] = "$dname" echo "S1: $k" $myMSCS.Add($k[0],$k[1]) } else { echo "S2: $k" $myMSCS.Add($k[0].Trim(),$k[1].Trim()) } } }

    Nun kann ich schön aus der Hash Table die Variablen entsprechend setzen, z.B. mit

    $global:CLUSTER_NAME = $myMSCS.Get_Item("CLUSTER_NAME")

    DISK_NAME (kann mehrfach vorkommen) werde ich das über eine Schleife abhandeln.

    Vielen Danke für den Schubbs in die richtige Richtung!

    Gruss

    Micha


    Freitag, 21. September 2012 10:02

Alle Antworten

  • Ich verstehe zwar was du möchtest, bin mir aber nicht sicher ob das das gewünschte Resultat bringt.

    Vergiss also mal kurz was du bisher gescriptet hast und beschreibe: wie soll genau das Ergebnis aussehen? Ein Vergleich Orginaldaten zu gewünschtem Resultat war sehr hilfreich.

    Grüße, Denniver


    Blog: http://bytecookie.wordpress.com

    Hilf mit und markiere hilfreiche Beiträge als "Hilfreich" und Beiträge die deine Frage ganz oder teilweise beantwortet haben als "Antwort".

    Donnerstag, 20. September 2012 12:01
    Moderator
  • Hallo Denniver,

    danke für Dein Feedback.

    Im Prinzip möchte ich den Inhalt des INI-Files in Varialen parsen. Also das aus

    ##################

    IP_ADDRESS=192.168.2.10
    IP_SUBNET=255.255.248.0
    #IP_NETWORK=AAA.AERO
    IP_NETWORK=Cluster Network 2
    NETNAME_NAME = DBNetNameSRP
    # make sure this host has ip 192.168.2.10
    NETNAME_VALUE = srm-clus-db
    NETNAME_DEPENDENCY = DBIPSRP
    DISK_NAME = Cluster Disk 2
    DISK_NAME = Cluster Disk 3
    DISK_NAME = Cluster Disk 4
    DISK_NAME = Cluster Disk 5

    ##################

    folgendes wird:

    $IP_ADDRESS="192.168.2.10"
    $IP_SUBNET="255.255.248.0"
    $IP_NETWORK="AAA.AERO"
    $IP_NETWORK="Cluster Network 2"
    $NETNAME_NAME="DBNetNameSRP"
    $NETNAME_VALUE="srm-clus-db"
    $NETNAME_DEPENDENCY="DBIPSRP"
    $DISK_NAME1="Cluster Disk 2"
    $DISK_NAME2="Cluster Disk 3"
    $DISK_NAME3="Cluster Disk 4"
    $DISK_NAME4="Cluster Disk 5"


    Wenn ich also beim anlegen der Hash Table eine ID mittels $count++ vorne dran hängen können würde wäre es mir dann möglich DISK_NAME entsprechend zu verwursten.

    Also das ich als Resultat folgende Hash Table hätte

    ID_|_NAME____________|_VALUE______
    1--|-IP_ADDRESS------|-192.168.2.10
    2--|-IP_SUBNET---------|-255.255.248.0
    3--|-IP_NETWORK------|-AAA.AERO
    4--|- IP_NETWORK------|-Cluster Network 2
    5--|-NETNAME_NAME--|-DBNetNameSRP
    ...

    7--|-DISK_NAME--------|-Cluster Disk 2
    8--|-DISK_NAME--------|-Cluster Disk 3
    9--|-DISK_NAME--------|-Cluster Disk 4
    10|-DISK_NAME--------|-Cluster Disk 5

    Vielen Dank!

    Gruss
    Micha


    • Bearbeitet Blacksheep70 Donnerstag, 20. September 2012 12:52
    Donnerstag, 20. September 2012 12:50
  • Mit einem Hashtable geht das so nicht, da du nur 2 Felder zur Verfügung hast (Key und Value).

     

    Das ganze lässt sich aber mit einem Array aus Objekten machen:
     

    Get-Content "$INIFILEPATH" | foreach-object -begin {
    	$myMSCS=@() ; $id = 0} -process { $k = [regex]::split($_,'='); $id++
    	if(($k[0].CompareTo("") -ne 0) -and ($k[0].StartsWith("[") -ne $True) -and ($k[0].StartsWith("#") -ne $True)) {
    
    			$obj = New-Object PSobject -Property @{
    				ID = $id
    				Name = $k[0].Trim()
    				Value = $k[1].Trim()			
    			}
    			$myMSCS += $obj
    		}		
    	}
    	
    $myMSCS | ft -AutoSize
     

    Vom Gefühl her würde ich sagen das ist eigentlich etwas Overkill, aber da du nicht erwähnt hast was du genau mit den Daten machen willst, ist dies der Weg um das von dir beschriebene Ergebnis zu erreichen.

    Grüße, Denniver

     


    Blog: http://bytecookie.wordpress.com

    Hilf mit und markiere hilfreiche Beiträge als "Hilfreich" und Beiträge die deine Frage ganz oder teilweise beantwortet haben als "Antwort".

    Donnerstag, 20. September 2012 14:09
    Moderator
  • Danke schön! Ich glaub das bringt mich gerade zumindest auf den richtigen Weg ;) Ich werd weiter probieren und meine Lösung dann hier posten.

    Wie gesagt: Alles was ich mit den Daten machen will ist sie in Variablen packen wobei es egal sein muss ob NAME (key) mehrfach vorkommt (natürlich MACHE ich intern dann nicht unique Werte in der Spalte NAME unique um sie als Variablen benutzen zu können)

    Prinzipiell geht es darum das Kunden ein Template der INI-Datei bekommen und diese manuell nach ihren Bedürfnissen pflegen müssen (nicht schlagen, ich kann für dieses Konzept nix!). Ich möchte nun ein Powershell Script schreiben welches den Inhalt dieser Datei auf Schlüssigkeit überprüft:

    o Sind die IPs erreichbar?
    o Ist der virtuelle Hostname im DNS?
    o Sind die Resourcen im MSCS richtig?

    usw. Dafür baruche ich den inhalt der Konfigurationsdatei als Variablen um sie als Settings verwerten zu können.

    Gruss

    Micha

    Donnerstag, 20. September 2012 15:50
  • So, ich glaube ich hab meine Lösung gefunden. Mag sein das es eleganter geht, aber für meine Laienhaften Powershell Kenntnisse finde ich das mal gar nicht schlecht:

    Get-Content "$INIFILEPATH" | foreach-object -begin {$myMSCS=@{};$id=0} -process { $k = [regex]::split($_,'=');$id++; if(($k[0].CompareTo("") -ne 0) -and ($k[0].StartsWith("[") -ne $True) -and ($k[0].StartsWith("#") -ne $True)) { $name = $k[0].Trim() $value = $k[1].Trim() if ($name.CompareTo("DISK_NAME") -eq 0){ $dname="$name$id" $k[0] = "$dname" echo "S1: $k" $myMSCS.Add($k[0],$k[1]) } else { echo "S2: $k" $myMSCS.Add($k[0].Trim(),$k[1].Trim()) } } }

    Nun kann ich schön aus der Hash Table die Variablen entsprechend setzen, z.B. mit

    $global:CLUSTER_NAME = $myMSCS.Get_Item("CLUSTER_NAME")

    DISK_NAME (kann mehrfach vorkommen) werde ich das über eine Schleife abhandeln.

    Vielen Danke für den Schubbs in die richtige Richtung!

    Gruss

    Micha


    Freitag, 21. September 2012 10:02