scriptex
Goto Top

Problem bei der Dateiverarbeitung mit PowerShell - Erstellen, Filtern, Vergleichen und Arbeiten im Text

Ich habe ein Problem bei einem PowerShell-Skript, das in und aus Dateien schreibt.

Hallo zusammen,

ich sitze momentan an einem Skript, dass Dateien auslesen, erstellen und vergleichen soll. Dabei soll auch in Dateien nach bestimmten Zeichen gesucht werden. Das funktioniert noch nicht ganz. Ich hoffe, ihr könnt mir weiterhelfen.

Zuerst sollen zwei Ursprungsdateien als Variablen festgelegt und ein Zielpfad angegeben werden:
$dat1 = "C:\source\1.dat"  
$dat2 = "C:\source\2.dat"  
$destination = "C:\Users\User\Desktop\"  

Diese Dateien werden automatisch generiert, sind recht lang und enthalten viel Zeug, das unwichtig ist. Jedoch tritt immer die gleiche Zeichenfolge ("sn:") vor verschiedenen Namen auf. Die Namen möchte ich herausfiltern und in eine neue, übersichtlichere Datei schreiben:

Get-ChildItem $dat1 | Select-String -pattern "sn:*" > "$destination\1_geordnet.txt"  
Get-ChildItem $dat2 | Select-String -pattern "sn:*" > "$destination\2_geordnet.txt"  

In den Dateien steht dann natürlich vor den Namen in der jeder Zeile der Pfad und die Line sowie das "sn:", da Select-String mir diese Eigenschaften mit angibt. Ich möchte aber einfach eine Liste mit den Namen erstellen. Ich habe es schon mit -replace versucht, d.h. alles vor den Namen durch "nichts" ersetzen zu lassen. Das greift aber nicht, da in dem Pfad in jeder Zeile ja "/" zu finden sind.

Wie kann ich also bereits die Ausgabe formatieren, dass mir nur die Namen angezeigt werden? Da ich mit Select-String suche, erhalte ich ja MatchInfo-Objekte als Ausgabe, und die Eigenschaft "Line" jedes Objektes ist genau der Name. Kann ich den rausfiltern?

Information: Die geordneten Dateien will ich dann im nächsten Schritt vergleichen und eine letzte Datei erstellen, die nur Unterschiede zwischen den Inhalten enthält. Das soll aber erstmal nicht Thema sein.
Das ist eines meiner ersten Skripts, versuche mich also erst langsam. Deswegen erwartet nicht mehr als Grundwissen von mir. Ich möchte mir alles nach und nach erarbeiten.

Ich hoffe, mir kann jemand helfen!
Gruß Scriptex

Content-ID: 180440

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

Ausgedruckt am: 05.11.2024 um 14:11 Uhr

Connor1980
Connor1980 13.02.2012 um 11:46:04 Uhr
Goto Top
Hi Scriptex

für unser aller besseres Verständnis: evtl kannst du noch ein Beispiel angeben wie es in 1.dat aussieht, wie es jetzt in 1_geordnet ankommt und wie es dort ankommen soll.

Grüße
Scriptex
Scriptex 13.02.2012 um 12:02:20 Uhr
Goto Top
In den .dat-Dateien sieht es ungefähr so aus:

changetype:...
pwdLastSet:...
sn:....
objectClass:...
ADsPath:LDAP:....
sAMAccountName:...
userAccountControl:..
userPrincipalName..

>
changetype:...
pwdLastSet:....
sn:..
etc.

Mich interessiert nur, was hinter "sn:" steht - und das möchte ich gerne rausschreiben; also eine Auflistung erstellen, wo nur die Namen, die hinter "sn:" stehen, enthalten sind.

Momentan steht es folgendermaßen in den geordneten Dateien:
C:\source\1.dat:3:sn:BEISPIELNAME1
C:\source\1.dat:21:sn:BEISPIELNAME2
C:\source\1.dat:30:sn:BEISPIELNAME3
C:\source\1.dat:39:sn:BEISPIELNAME4
C:\source\1.dat:48:sn:BEISPIELNAME5
C:\source\1.dat:57:sn:BEISPIELNAME6
C:\source\1.dat:66:sn:BEISPIELNAME7

Also: Pfad - Datei - Linie - mein Suchstring "sn:*"

Ich möchte eine Datei erstellen, wo so gesehen nur das * drinsteht.
bastla
bastla 13.02.2012 um 22:03:19 Uhr
Goto Top
Hallo Scriptex und willkommen im Forum, hallo Connor1980!

Vielleicht hilft ja die Beschreibung hier ...

Als Batch sähe das übrigens so aus:
for /f "tokens=1* delims=:" %%i in ('findstr /b "sn:" "C:\source\1.dat"') do >>"C:\Users\User\Desktop\1_geordnet.txt" echo %%j
Grüße
bastla
Scriptex
Scriptex 14.02.2012 um 09:14:15 Uhr
Goto Top
Hallo bastla!

dein Code funktioniert einwandfrei, genau so soll das Ergebnis aussehen. Als Notlösung geht es also, wenn ich zweigleisig (Batch und Shell) fahre. Aber das Ziel soll ein fertiges PS-Skript sein. Doch warum lässt sich das mit PowerShell nicht realisieren?

Beim Rumprobieren ist folgender Code rausgekommen:
(Get-Content "C:\Users\User\Desktop\1_geordnet.txt") | Foreach-Object {$_ -replace '*sn:', ''} | Set-Content "C:\Users\User\Desktop\1_fertig.txt"  

Da bekomme ich jedoch den Fehler, dass *sn: kein regulärer Ausruck sei. Wenn das bloß nicht wäre...


Einen anderen Ansatz hatte ich oben schon kurz angeschnitten: MatchInfo. Also die Informationen, die ich mir zu jedem gefundenen "sn:" in jeder Zeile mit anzeigen lassen kann. Neben Properties wie LineNumber, Path und FileName gibt es auch die Eigenschaft Line, die evtl. helfen könnte.
Benutze ich also folgenden Code zum Anzeigen der MatchInfo:
Select-String -pattern "sn:*" -Path "Pfad" | Format-List  
hängt der Eintrag in der Line-Property von der Quelldatei ab. Benutze ich die geordnete Datei ("$destination\1_geordnet.txt") ist der Line-Eintrag die ganze Zeile (also etwa C:\source\1.dat:3:sn:BEISPIELNAME1). Gebe ich aber die Ursprungsdatei an ("C:\source\1.dat"), so ist der Line-Eintrag nur "sn:BEISPIELNAME1". Wie kann ich diese Line-Property einzeln anzeigen lassen und dann in einer Datei speichern? Das wäre doch sicher einfacher.

Bis dahin schon mal recht vielen Dank.
Gruß Scriptex
bastla
bastla 14.02.2012 um 11:59:01 Uhr
Goto Top
Hallo Scriptex"

Leider ist PS (noch immer) nicht meine Sprache - deswegen hatte ich auch die Analogie zur "for /f"-Schleife gesucht das oben verlinkte Suchergebnis gefunden. Hast Du es mit "split" schon versucht?

Grüße
bastla
Scriptex
Scriptex 14.02.2012 um 15:35:52 Uhr
Goto Top
Ich bin über split und replace zu .SubString gekommen. Da ich die Position in der Zeile kenne, bietet sich das an. Ich habe mich eben an einem Code versucht, der jedoch auf Anhieb nicht funktioniert hat. Das Problem sehe ich momentan darin, dass SubString die Daten noch nicht richtig erhält. Den Inhalt der Datei in eine Variable zu speichern hat geklappt. Das Weiterleiten per Pipe an SubString scheint nicht richtig zu greifen. Ich habe mit einer ForEach-Schleife versucht, jede Zeile der Datei an SubString weiterzuleiten, dort soll dann durch die Positionsangabe nur bestimmter Text ausgegeben werden. Leerstellen und andere überschüssige Zeichen wollte ich dann im nächsten Schritt mit replace entfernen.
So weit bin ich aber gar nicht erst gekommen, da die Zeilen von SubString wohl nicht als 'Objekte' erkannt werden oder die Daten (der Inhalt der Datei) nicht korrekt übergeben werden. Versuche es aber noch weiter.
Hier der code momentan:

1. Versuch
$content | % { $_.Line.Substring(83,17) } 
2. Versuch
$content | % { $_.Line.Substring($_.Line.LastIndexOf('sn:')) }   
Anm.: $content= Get-Content "$destination\1_geordnet.txt"

So far,
Scriptex
Scriptex
Scriptex 17.02.2012 um 09:20:01 Uhr
Goto Top
Hallo,

ich bin mittlerweile etwas weiter gekommen. Ich habe jetzt die Namen einzeln in der Datei. Die nächsten Schritte sind:
- leere Zeilen aus der Datei entfernen
- Den ganzen Prozess für die 2. Datei durchlaufen
- die so entstandenen zwei Dateien (enthalten dann nur Namen) auf Unterschiede vergleichen und die Unterschiede in eine Ergebnis-Datei schreiben.

Der bisherige Code:
# Die zwei Roh-Dateien einlesen #
$dat1 = "C:\source\1.dat"  
$dat2 = "C:\source\2.dat"   

# Ziel-Pfad angeben #
$destination = "C:\Users\User\Desktop\"  

# Die richtigen Zeilen aus jeder Datei filtern und in neue Datei schreiben # 
Select-String -pattern "sn:*" -Path $dat1 | Format-List -Property Line > "$destination\temp1.txt"  
Select-String -pattern "sn:*" -Path $dat2 | Format-List -Property Line > "$destination\temp2.txt"  

# Überbleibsel aus der Roh-Datei (bestimmter String) aus dem Inhalt der gefilterten Dateien löschen #
Get-Content "$destination\temp1.txt" | % {$_ -replace "Line : sn:", ""} | Set-Content "$destination\temp1.txt"  
Get-Content "$destination\temp2.txt" | % {$_ -replace "Line : sn:", ""} | Set-Content "$destination\temp2.txt"  

# Inhalt der Dateien in Variablen schreiben #
$clear1 = Get-Content "$destination\temp1.txt"  
$clear2 = Get-Content "$destination\temp2.txt"  

# leere Zeilen in jeder Datei suchen und entfernen #
ForEach ($line in $clear1) { if ($line.Substring(0) -ne "") { Write-Host $line} }  
ForEach ($line in $clear2) { if ($line.Substring(0) -ne "") { Write-Host $line} }  


Beim Löschen der leeren Zeilen habe ich noch das Problem, dass mir durch Write-Host die Namen untereinander (genau so, wie ich es haben möchte) in der PowerShell nach dem Ausführen des Befehls angezeigt werden. Ich möchte sie aber in einer Datei namens Dat.txt oder so speichern. Write-Host ist dafür imo nicht geeignet. Aber Out-File oder ConvertTo-Html funktionieren in der if-Anweisung irgendwie nicht. Am liebsten würde ich das mit Set-Content machen, bisher hat aber noch keiner meiner Versuche funktioniert.

Wie oben angesprochen, möchte ich dann die beiden Dateien vergleichen und daraus schlussendlich die End-Datei erstellen. Abfragen für die Pfade sollen auch noch dazukommen.
Ich halte den Thread hier auf dem Laufenden.

Scriptex