mars123
Goto Top

Powershell Script zum ändern von bestimmten Strings funktioniert nicht richtig

Guten Tag,

ich arbeite momentan an einem Powershell Script das bestimmte Strings in einer Textdatei sucht und durch einen anderen definierten String ersetzen soll.

Dies funktioniert leider nur teilweise, da plötzlich manche Strings doppelt vorhanden sind. Einmal der abgeänderte String und einmal der vorherige String.

Das Script soll bewirken, dass die Namen des Strings ersetzt werden und nicht mehr durch ein Leerzeichen getrennt sind, damit diese korrekt in eine Excel Tabelle eingefügt werden können.

Über Hilfe wäre ich sehr dankbar!

$lookupTable = @{

    'Windows Server© 2008 Standard ohne Hyper-V' = 'WindowsServer©2008StandardohneHyper-V'  
    'Windows Server© 2008 Standard' = 'WindowsServer©2008Standard'  
    'Windows Server 2008 R2 Datacenter' = 'WindowsServer2008R2Datacenter'  
    'Windows Server 2003' = 'WindowsServer2003'  
    'Windows XP Professional' = 'WindowsXPProfessional'  
    'Windows 2000 Professional' = 'Windows2000Professional'      
    'Windows Server 2008 R2 Standard' = 'WindowsServer2008R2Standard'  
    'Windows NT' = 'WindowsNT'  
    'EMC Celerra File Server' = 'EMCCelerraFileServer'  
    'Windows VistaT Business' = 'WindowsVistaTBusiness'  
    'Windows Server 2008 R2 Enterprise' = 'WindowsServer2008R2Enterprise'  
    'Windows Server© 2008 Enterprise' = 'WindowsServer©2008Enterprise'  
    'Windows Server 2012 R2 Standard' = 'WindowsServer2012R2Standard'  
    'Windows Server 2012 R2 Datacenter' = 'WindowsServer2012R2Datacenter'  
    'macmon appliance' = 'macmonappliance'  
    'Windows 8.1 Enterprise' = 'Windows8.1Enterprise'  
    'Windows 7 Ultimate' = 'Windows7Ultimate'  
    'Windows 7 Professional' = 'Windows7Professional'  
    'Windows 2000 Server' = 'Windows2000Server'  
    'Windows 8 Pro' = 'Windows8Pro'  
    'Windows 7 Enterprise N' = 'Windows7EnterpriseN'  
    'Windows 7 Professional N' = 'Windows7ProfessionalN'  

}

$original_file = 'N:\SAM\Serverliste\compneu.txt'  
$destination_file =  'N:\SAM\Serverliste\compneu1.txt'  

Get-Content -Path $original_file | ForEach-Object { 
    $line = $_

    $lookupTable.GetEnumerator() | ForEach-Object {
        if ($line -match $_.Key)
        {
            $line -replace $_.Key, $_.Value
            
        }
    }
} | Set-Content -Path $destination_file

Content-ID: 315118

Url: https://administrator.de/contentid/315118

Ausgedruckt am: 25.11.2024 um 14:11 Uhr

colinardo
colinardo 13.09.2016 aktualisiert um 11:59:04 Uhr
Goto Top
Hallo Mars123,
ein Grund ist das -replace Regular Expressions verwendet, d.h. also das Sonderzeichen wie Punkte Dollarzeichen etc. besondere Bedeutung haben. Außerdem gibst du die geänderten Zeilen überhaupt nicht aus. und das einzelne durchlaufen der Zeilen ist ebenfalls nicht nötig und überflüssig das Replace mit Arrays umgehen kann.

Optimiert lässt sich das folgendermaßen machen. (Das Aufführen der Replacement-Strings ohne Leerzeichen ist hier nicht nötig, das das hier mit einem Regex-Iterator-Object automatisch gemacht wird:
$lookupTable = @(
    'Windows Server© 2008 Standard ohne Hyper-V'  
    'Windows Server© 2008 Standard'  
    'Windows Server 2008 R2 Datacenter'  
    'Windows Server 2003'  
    'Windows XP Professional'  
    'Windows 2000 Professional'  
    'Windows Server 2008 R2 Standard'  
    'Windows NT'  
    'EMC Celerra File Server'  
    'Windows VistaT Business'  
    'Windows Server 2008 R2 Enterprise'  
    'Windows Server© 2008 Enterprise'  
    'Windows Server 2012 R2 Standard'  
    'Windows Server 2012 R2 Datacenter'  
    'macmon appliance'  
    'Windows 8.1 Enterprise'  
    'Windows 7 Ultimate'  
    'Windows 7 Professional N'  
    'Windows 7 Professional'  
    'Windows 2000 Server'  
    'Windows 8 Pro'  
    'Windows 7 Enterprise N'  
)
$original_file = 'N:\SAM\Serverliste\compneu.txt'  
$destination_file =  'N:\SAM\Serverliste\compneu1.txt'  

# make regex 'or' expression 
$lookuptable = ($lookupTable | %{[regex]::Escape($_)}) -join '|'  
# replace with regex iterator
[regex]::replace((gc -Path $original_file | out-string),$lookupTable,{param($m) $m.Value -replace '\s',''}) | set-content $destination_file  
Grüße Uwe
Mars123
Mars123 13.09.2016 aktualisiert um 11:51:21 Uhr
Goto Top
Erst einmal Danke für deine Antwort Uwe.

Das funktioniert insoweit ganz gut, dass keine doppelten Einträge mehr in der Ausgabedatei vorhanden sind.

Jedoch werden bei den im Array aufgeführten Strings nicht alle Leerzeilen entfernt.

Beispiel: Aus 'Windows 7 Professional N' wird 'Windows7Professional N'

Glaube das war soweit auch der einzige String den ich bisher gefunden habe.

Wenn das noch klappen würde, wäre ich überaus zufrieden! face-smile
Mars123
Mars123 13.09.2016 um 11:53:27 Uhr
Goto Top
Zitat von @Mars123:

Erst einmal Danke für deine Antwort Uwe.

Das funktioniert insoweit ganz gut, dass keine doppelten Einträge mehr in der Ausgabedatei vorhanden sind.

Jedoch werden bei den im Array aufgeführten Strings nicht alle Leerzeilen entfernt.

Beispiel: Aus 'Windows 7 Professional N' wird 'Windows7Professional N'

Glaube das war soweit auch der einzige String den ich bisher gefunden habe.

Wenn das noch klappen würde, wäre ich überaus zufrieden! face-smile

Ich habe es nochmal durchlaufen lassen, über die letzte Ausgabedatei und habe nun das gewünschte Ergebnis, damit kann ich leben. Ich danke dir vielmals Uwe! face-smile

Gruß,

Marcel
colinardo
colinardo 13.09.2016 aktualisiert um 12:17:29 Uhr
Goto Top
Zitat von @Mars123:
Jedoch werden bei den im Array aufgeführten Strings nicht alle Leerzeilen entfernt.

Beispiel: Aus 'Windows 7 Professional N' wird 'Windows7Professional N'

Glaube das war soweit auch der einzige String den ich bisher gefunden habe.

Wenn das noch klappen würde, wäre ich überaus zufrieden! face-smile
Ist oben angepasst, lag in dem Fall an der Reihenfolge.


Hier noch eine mögliche Variante , die für dich vielleicht leichter verständlich ist:
$lookupTable = @(
    'Windows Server© 2008 Standard ohne Hyper-V'  
    'Windows Server© 2008 Standard'  
    'Windows Server 2008 R2 Datacenter'  
    'Windows Server 2003'  
    'Windows XP Professional'  
    'Windows 2000 Professional'  
    'Windows Server 2008 R2 Standard'  
    'Windows NT'  
    'EMC Celerra File Server'  
    'Windows VistaT Business'  
    'Windows Server 2008 R2 Enterprise'  
    'Windows Server© 2008 Enterprise'  
    'Windows Server 2012 R2 Standard'  
    'Windows Server 2012 R2 Datacenter'  
    'macmon appliance'  
    'Windows 8.1 Enterprise'  
    'Windows 7 Ultimate'  
    'Windows 7 Professional N'  
    'Windows 7 Professional'  
    'Windows 2000 Server'  
    'Windows 8 Pro'  
    'Windows 7 Enterprise N'  
)
$original_file = 'N:\SAM\Serverliste\compneu.txt'   
$destination_file =  'N:\SAM\Serverliste\compneu1.txt'  
$content = gc $original_file
$lookupTable | %{
    $content = $content -replace [regex]::Escape($_),($_ -replace '\s','')  
}
$content | set-content $destination_file
Mars123
Mars123 13.09.2016 um 15:28:07 Uhr
Goto Top
Nun stehe ich wiederum vor dem Problem, dass ich in der Textdatei für jeden Server einen distiguished Name habe, in dem sich auch wieder Leerzeichen befinden und ich die CNs und OUs nicht ordnungsgemäß trennen kann. Hast dafür ne Idee?
Mars123
Mars123 13.09.2016 um 16:04:52 Uhr
Goto Top
Ich habs mit regex probiert, aber schaffe es nicht nur einen bestimmten Bereich einzugrenzen, in dem die Leerzeichen gelöscht werden sollen.
colinardo
colinardo 13.09.2016 aktualisiert um 20:56:37 Uhr
Goto Top
Zitat von @Mars123:

Nun stehe ich wiederum vor dem Problem, dass ich in der Textdatei für jeden Server einen distiguished Name habe, in dem sich auch wieder Leerzeichen befinden und ich die CNs und OUs nicht ordnungsgemäß trennen kann. Hast dafür ne Idee?
Erkläre doch mal genau was du willst machen (extrahieren/ersetzen) willst. Mit einer passenden Regular Expression ist das im Handumdrehen erledigt.
aber schaffe es nicht nur einen bestimmten Bereich einzugrenzen, in dem die Leerzeichen gelöscht werden sollen.
Wenn ich wüsste was du wo ersetzen willst alles kein Problem,
Du musst mir schon sagen ob im CN oder OU Bereich Leerzeichen ersetzt werden sollen etc.

Ein Replacement Pattern für einen CN könnte z.B. so aussehen:
CN=(.*?)(?=,(CN|OU|DC))
Das ganze dann wie oben mit einem Replacement iterator mit Eliminierung der Spaces abgefackelt, fertig.

By the way, was ist der Sinn und Zweck der Ersetzung der Leerzeichen? Nur für eine Excel-Aufbereitung? Dafür gibt es wesentlich bessere Methoden wenn man auf andere Delimiter setzt, das Leerzeichen ist da alles andere als optimal wie du gerade feststellst face-smile. In Powershell gibt es diverse Methoden um ein File Excel freundlich umzubauen, vielleicht kann ich dir dein Vorhaben ja etwas optimieren und du kennst vielleicht einige dieser Tricks noch nicht.

[OT] Ich habe ja normalerweise keine Probleme damit, aber das Ausschweifen mit Fragen in einem Thread der von etwas anderem handelt sehen wir hier eigentlich nicht so gerne, zumal das für die Leute die hier vorbei schauen mehr als verwirrend ist.
Melde dich doch via PM mit deinen weiteren Fragen und markiere den Thread hier als gelöst. Merci.
[/OT]
Mars123
Mars123 14.09.2016 aktualisiert um 08:31:23 Uhr
Goto Top
Wir haben mit einem Tool unser AD ausgelesen und diese Auflistung wurde in einer .txt Datei gespeichert. Wir brauchen die Einträge jedoch aufgeteilt in einer Excel Tabelle, damit wir diese auswerten können.

Eine Zeile in der Textdatei sieht wie folgt aus:

L-DC-02            Windows Server© 2008 Standard                 6.0 (6002)                CN=L-DC-02,OU=Domain Controllers,DC=geno,DC=intern 

Die Felder sind halt durch keinen Feldtrenner so getrennt, dass man sie ohne Probleme aufteilen könnte. Alle Whitespaces löschen geht auch nicht, da ich die einzelnen Werte nicht mehr auseinander bekomme. Da die Liste endlos lang ist (ca. 4000 Einträge), lässt sich das auch nicht einzeln durchführen.

Wenn es da einen Trick gibt oder eine Methode die ich noch nicht kenne, wäre ich sehr froh darüber, wenn du sie mir verraten könntest.
Mars123
Mars123 14.09.2016 aktualisiert um 08:28:06 Uhr
Goto Top
Entschuldige bitte dass ich hier etwas ausgeschweift bin, dachte auch das Problem ließe sich durch das bloße ersetzen der Strings lösen und hat dann aber zu einem anderen Problem geführt face-sad
colinardo
colinardo 14.09.2016 aktualisiert um 08:40:45 Uhr
Goto Top
Zitat von @Mars123:

Wir haben mit einem Tool unser AD ausgelesen
Dann war dieses Tool aber nicht besonders toll, mit Leerzeichen trennen?? welcher Depp macht den sowas ??
Das AD kannst du doch bequem mit der Powershell selbst mit den AD-CMDlets (Get-ADComputer) oder per LDAP auslesen.
Damit kann man das gleich schön als CSV formatiert ausgeben.
Also absolut unverständlich sich jetzt die Mühe zu machen das wieder auseinander zu pflücken was zudem Fehleranfällig sein ist.


Eine Zeile in der Testdatei sieht wie folgt aus:

M-DC-02 Windows Server© 2008 Standard 6.0 (6002) CN=M-DC-02,OU=Domain Controllers,DC=geno,DC=intern

OK.
Die Felder sind halt durch keinen Feldtrenner so getrennt,
Das zum Thema Tool face-smile
Wenn es da einen Trick gibt oder eine Methode die ich noch nicht kenne, wäre ich sehr froh darüber, wenn du sie mir verraten könntest.
Wenn deine Felder bestimmte Muster aufweisen z.B. manche Felder nur Zahlen oder anderes lässt sich das in einen Pattern pressen, ich würde aber definitiv den Weg gehen das vernünftig via Ldap/ AD-CMDLets aufzuziehen und es direkt vernünftig auszugeben.

Mit Get-ADComputer kommst du zudem an alle Infos von oben, dann mit select die gewünschten Felder selektieren und du dann das ergebnis direkt an Export-CSV pipen.
Mars123
Mars123 14.09.2016 um 08:48:31 Uhr
Goto Top
Das Tool kommt von einer großen IT Firma die für uns die Lizensierung unserer Server macht, das wurde echt dumm umgesetzt.

Gibt es denn die Möglichkeit, eine variable Anzahl von Leerzeichen durch z.B. ein # zu ersetzen? Bzw. sobald mehr als ein Whitespace aufeinanderfolgend auftritt? An solch einer Lösung wäre ich auf jeden Fall auch für die Zukunft interessiert.
colinardo
Lösung colinardo 14.09.2016 aktualisiert um 08:55:38 Uhr
Goto Top
Bist du sicher das das keine Tabs sind ?
Zitat von @Mars123:
Gibt es denn die Möglichkeit, eine variable Anzahl von Leerzeichen durch z.B. ein # zu ersetzen? Bzw. sobald mehr als ein Whitespace aufeinanderfolgend auftritt? An solch einer Lösung wäre ich auf jeden Fall auch für die Zukunft interessiert.
Ja klar du kannst per regex 'splitten'
Hiermit benutzt du dann bei mindestens 2 aufeinander folgenden Spaces als Trenner, in $columns sind dann die einzelnen Daten der aktuellen Zeile der Schleife als Array enthalten.
gc file.txt | %{
    $columns = $_ -split '\ {2,}'  
}
Mars123
Mars123 14.09.2016 um 09:16:36 Uhr
Goto Top
Das würde natürlich super funktionieren, nur bräuchte ich als Feldtrenner zwischen den Strings ein anderes Zeichen als das Leerzeichen, weil sonst stehe ich wieder vor dem Problem, dass bestimmte CNs wieder getrennt werden die zusammen gehören.
Mars123
Mars123 14.09.2016 um 09:19:13 Uhr
Goto Top
Ich habs jetzt so gelöst:

gc N:\SAM\Serverliste\compneu.txt | %{
$columns = $_ -replace '\ {2,}','#'  
}

Das ganze in einer Schleife funktioniert einwandfrei.

Ich danke dir für deine Hilfe und wünsche dir eine schöne Woche! face-smile
colinardo
colinardo 14.09.2016 aktualisiert um 09:25:20 Uhr
Goto Top
Zitat von @Mars123:

Das würde natürlich super funktionieren, nur bräuchte ich als Feldtrenner zwischen den Strings ein anderes Zeichen als das Leerzeichen,
Wieso ?? Du hast CNs bei denen du mehr als zwei direkt aufeinanderfolgende Leerzeichen haben? Das wäre sehr sehr ungewöhnlich und würde auf ein sehr unsauber geführtes AD hinweisen.

Wir drehen und im Kreis, lese die Daten direkt per Get-ADComputer aus und du bist in 5 Minuten fertig, ich sehe hier absolut keine Probleme, sorry. Das ist lächerliches Anfängerskripting.

Wenn du mir sagst welche Computer und welche Felder du auslesen willst, schreibe ich dir das schnell zusammen, du wirfst das Script auf einem DC oder einer WS mit RSAT an und feddich.
colinardo
colinardo 14.09.2016 aktualisiert um 09:34:30 Uhr
Goto Top
Zitat von @Mars123:
gc N:\SAM\Serverliste\compneu.txt | %{
> $columns = $_ -replace '\ {2,}','#'  
> }

Wieso jetzt wieder durch ein anderes ersetzen nur um dann hinterher wieder zu splitten?

Ich würde da direkt eine vernünftige CSV draus machen, die sich sofort mit Excel öffnen lässt.
gc N:\SAM\Serverliste\compneu.txt | %{
    $columns = $_ -split '\ {2,}'  
    [pscustomobject] @{Name=$columns;OS=$columns[1]}
} | export-CSV 'c:\export.csv' -delim ";" -NoType -Encoding UTF8  
Die weiteren Spalten solltest du jetzt im Object ergänzen können.

Viele Grüße und ebenso eine schöne Woche
Uwe