forseti2003
Goto Top

Powershell: mehrere identische Zeilen

Guten Morgen,

kurz vor Weihnachten steh ich aktuell vor einer harten Nuss, eventuell hat jemand eine Idee, wie man das mit PowerShell auflösen kann.

Das Problem:
Ich erhalte eine Textdatei mit Satzarten. Nun kommt es gelegentlich vor, das in einer Datei Daten mehrfach vorhanden sind

Beispiel:
0200 51 A123456-1 010151
0300 51 A123456-1   10000 Text1
0300 51 A123456-1   20000 Text2
0200 51 A123456-1 010151
0300 51 A123456-1   10000 Text1
0300 51 A123456-1   20000 Text2

Eigentlich bräuchte ich nur die letzten drei Eintragungen. Die oberen drei sind nur doppelt. In der Datei können aber auch noch zusätzliche Aufträge vorhanden sein, nicht nur ein Auftrag, also zwingend auf die letzten Zeilen kann ich nicht verweisen. Ich müsste ermitteln, wieviele gleiche Zeilen es gibt:

0300 - A1234456-1 10000 ist 2x vorhanden, überspringe die alle, bis zum letzten Eintrag und mach dann weiter.

Eigentlich würde ich jetzt über eine for-Schleife nachdenken, die Zähler ermitteln und dann erst einen Schreibvorgang auslösen, wenn ich mit dem Zähler auf der letzten Position wäre. Wie kann ich das aber in Powershell elegant lösen?

Content-ID: 529288

Url: https://administrator.de/forum/powershell-mehrere-identische-zeilen-529288.html

Ausgedruckt am: 27.12.2024 um 21:12 Uhr

emeriks
emeriks 23.12.2019 aktualisiert um 09:43:07 Uhr
Goto Top
Hi,
reicht dafür nicht Get-Unique ?

Get-Content $filename | Get-Unique

E.
Forseti2003
Forseti2003 23.12.2019 um 09:52:02 Uhr
Goto Top
Leider nicht, wenn ich Get-Unique an Get-Content anhänge, erhalte ich auch alle Datensätze.
Kraemer
Kraemer 23.12.2019 um 10:06:14 Uhr
Goto Top
Get-Content .\test.txt | Sort-Object | Get-Unique
142232
142232 23.12.2019 aktualisiert um 10:46:45 Uhr
Goto Top
Hier drei mögliche Varianten, die alle zum Ergebnis führen
https://tio.run/##tYzBCoJAEIbv@xTDUkdlZ80OQWAnX6C6RITIZMLi2jqSUD37pheJED ...

Variante 1:"  
"============="  
gc test.txt | select -Unique

"Variante 2:"  
"============="  
gc test.txt | sort | Get-Unique

"Variante 3:"  
"============="  
gc test.txt | group | %{$_.Group}

Such dir eine aus und dann frohes Fest!

s.
Forseti2003
Forseti2003 23.12.2019 um 10:50:11 Uhr
Goto Top
ja mit dem Zusatz Sort-Object scheint es soweit zu funktionieren. Gibt zwar dann noch Probleme, sollte die Zeile im Auftrag nicht identisch sein, aber das stört aktuell nicht. Danke euch beiden für den Hinweis.
Forseti2003
Forseti2003 23.12.2019 um 11:02:35 Uhr
Goto Top
Hallo serial,

der tio.run Link ist ja cool - ich hab mich aktuell mal für die sort-Methode entschieden. Hoffentlich klappt es.

Wünsche euch auch allen ein frohes Fest

Forseti
Forseti2003
Forseti2003 23.12.2019 um 12:44:22 Uhr
Goto Top
Update - leider bringt es doch nichts.
Wie ich nun in einigen Dateien später feststelle, kann es auch passieren, das die Sätze unterschiedlich sind.
Damit erhalte ich dann als Ausgabe:

0200 A123456
0300 A123456 ABC 4
0300 A123456 CDE 4
0300 A123456 ABC 5
0300 A123456 CDE 5

Damit wäre die Zeile 2 und 4 mit sich selbst identisch. Zum weitere verarbeiten ist aber nur die Zeile 4 erforderlich.
Gleiches gilt für Zeile 3 und 5.

Wäre jetzt mit dem Anhängsel get-unique auch zu schön gewesen.
Damit muss ich also definitiv immer auf die letzten Datensätze zu einer Auftragsnummer verweisen.

Also so:
0200 A123456
0300 A123456 ABC 5
0300 A123456 CDE 5
142232
142232 23.12.2019 aktualisiert um 12:56:14 Uhr
Goto Top
Zitat von @Forseti2003:

Update - leider bringt es doch nichts.
Wie ich nun in einigen Dateien später feststelle, kann es auch passieren, das die Sätze unterschiedlich sind.
Damit erhalte ich dann als Ausgabe:

0200 A123456
> 0300 A123456 ABC 4
> 0300 A123456 CDE 4
> 0300 A123456 ABC 5
> 0300 A123456 CDE 5

Damit wäre die Zeile 2 und 4 mit sich selbst identisch. Zum weitere verarbeiten ist aber nur die Zeile 4 erforderlich.
Gleiches gilt für Zeile 3 und 5.
Falsch Get-Unique arbeitet hier völlig korrekt denn die Zeilen sind hier ja wirklich unterschiedlich, die Zahl am Ende ist nicht gleich also ist das für Get-Unique ein anderer Datensatz weil es ja die ganze Zeile vergleicht!


Damit muss ich also definitiv immer auf die letzten Datensätze zu einer Auftragsnummer verweisen.

Also so:
0200 A123456
> 0300 A123456 ABC 5
> 0300 A123456 CDE 5
Nein, z.B. per Import-CSV kann man leicht die Spalten im Eigenschaften wandeln und selektieren welche Spalten für einen Datensatz-Vergleich herhalten sollen.
Forseti2003
Forseti2003 23.12.2019 um 12:57:37 Uhr
Goto Top
Zitat von @142232:

Falsch Get-Unique arbeitet hier völlig korrekt denn die Zeilen sind hier ja wirklich unterschiedlich, die Zahl am Ende ist nicht gleich also ist das für Get-Unique ein anderer Datensatz weil es ja die ganze Zeile vergleicht!

Ich sag ja nicht das Get-Unique an sich falsch arbeitet - aber es bringt nicht das Ergebnis, das ich benötige.

Nein, z.B. per Import-CSV kann man leicht die Spalten im Eigenschaften wandeln und selektieren welche Spalten für einen Datensatz-Vergleich herhalten sollen.

Es ist eine reine Text-Datei, der Import via CSV scheidet daher aus.
142232
Lösung 142232 23.12.2019 aktualisiert um 13:15:50 Uhr
Goto Top
Es ist eine reine Text-Datei, der Import via CSV scheidet daher aus.
Nein, das geht auch damit face-wink. Mit einer Foreach-Schleife und der Split-Funktion auch.
Für dein Beispiel
gc test.txt | %{
    $obj = [ordered]@{}
    $columns = $_ -split '\s+'  
    1..($columns.Count) | %{$obj.$_ = $columns[$_]}
    [pscustomobject]$obj
} | group "1","2","3" | %{$_.Group[-1]}  

Oder etwas kürzer ohne Erstellung eines Objects geht es auch so
gc test.txt | group {($_ -split '\s+')[0..2] -join ";"} | %{$_.Group[-1]}   
Forseti2003
Forseti2003 23.12.2019 aktualisiert um 14:14:48 Uhr
Goto Top
Der letzte Befehl scheint fast richtig zu funktionieren - er erzeugt zumindest nur noch in zwei Datensätze eine Abweichung.
Ich schätze das ich da noch was anpassen muss, aber ich kapier aktuell nicht, wie die Zeile funktioniert.
Wenn Du mir da noch kurz auf die Sprünge helfen könntest face-wink

Ich vermute mal, das [0..2] die Anzahl der Spalten sein soll und -join ";" das Trennzeichen.
Wenn ich in bei meinen Daten auf 0..4 gehe und anstelle von ; " " setze, scheint das Ergebnis zu passen, oder habe ich da noch einen Denkfehler?
142232
Lösung 142232 23.12.2019 aktualisiert um 14:32:05 Uhr
Goto Top
Du musst halt richtig spezifizieren anhand welcher Merkmale du doppelte Wert identifizieren willst (das hast du immer noch nicht getan), beide Skripts oben machen das gleiche sie nehmen nur die ersten 3 Spalten (getrennt anhand von einem oder mehreren Leerzeichen), also bspw. diese hier
0300 51 A123456-1
und vergleichen nur diese mit Group-Object, dann wird von jeder Gruppe nur der letzte Eintrag (Zeile) komplett ausgegeben.
Das Trennzeichen beim Join ist beliebig das ist zufällig gewählt hat hier für die Aufgabe tatsächlich aber keine Funktion, das fasst das SplitArray für Group-Object nur zu einer Zeile zusammen. Für die Spaltentrennung ist der Regex \s+ zuständig, das war mir am naheliegendsten da du uns auch keine definitive Spaltentrennung geliefert hast, oben sind nämlich mal einzelne und dann wieder mehrere aufeinanderfolgende Leerzeichen zwischen den Spalten.

oder habe ich da noch einen Denkfehler?
Dein Denkfehler ist das du uns keine verlässlichen Infos geliefert hast anhand welcher Merkmale eine Zeile als Duplikat zu betrachten ist! Wir kennen deine Daten geschweige den irgendwelche Spaltenüberschriften nicht und können daher dein Daten nicht zuordnen und auch nur ahnen was für dich tatsächlich relevant ist oder eben nicht.

Schau dir einfach mal das Ergebnis von Group-Object alleine auf der Konsole an dann siehst du wie das funktioniert.
Forseti2003
Forseti2003 23.12.2019 um 14:34:43 Uhr
Goto Top
Danke für Deine Geduld, mit den entsprechenden Anpassungen klappt die Ausgabe nun richtig.
142232
142232 23.12.2019 aktualisiert um 14:37:18 Uhr
Goto Top
Schön, dann fürs nächste mal bitte gleich im Ursprungspost die entsprechenden Spezifikationen hier rein schreiben, das spart uns jede Menge Aufklärungsarbeit und Missverständnisse face-smile. Danke.

Frohes Fest.