CSV Datei in PS bearbeiten und wieder speichern

Mitglied: Hacktrist

Hacktrist (Level 1) - Jetzt verbinden

15.04.2021, aktualisiert 16.04.2021, 907 Aufrufe, 28 Kommentare, 1 Danke

Hallo Liebe Administrator Gemeinde.

Ich habe folgendes Anliegen, ich habe eine immer wieder kehrende Aufgabe welche ich gern automatisieren möchte.

Es gibt eine Date welche zum Beispiel "Pfusch1.csv" heißt und im Ordner C:\ErstePSErfahrung\ liegt.
Die csv Datei hat ein ; als trennzeichen und ist mit folgendem Inhalt versehen.

Spalte1;Spalte2;;;Spalte5;Spalte6;
Spalte1;Spalte2;;;Spalte5;Spalte6;

daraus möchte ich nun den Inhalt der Spalte2 löschen (aber nicht die ganze Spalte).

Spalte1;;;;Spalte5;Spalte6;
Spalte1;;;;Spalte5;Spalte6;

Im Anschluss soll die Datei wieder im Ordner C:\ErstePSErfahrung\ gespeichert werden.

Ich könnte mir das unter Linux durch einen Import, den sed Befehl und anschließendem Export schreiben.

Von Powershell haber ich bisher noch keine Erfahrungen sammeln können und hoffe auf Eure Unterstützung.

Beginnen würde ich das Skript mit

28 Antworten
Mitglied: TK1987
LÖSUNG 15.04.2021, aktualisiert um 14:36 Uhr
Moin,

Zitat von @Hacktrist:
Beginnen würde ich das Skript mit
besser direkt mit Import-CSV, so kannst du die Spalten auch direkt ansteuern.

Von Powershell habe ich bisher noch keine Erfahrungen sammeln können und hoffe auf Eure Unterstützung.

Ein bisschen was zum lesen:

Gruß Thomas
Bitte warten ..
Mitglied: Hacktrist
15.04.2021, aktualisiert um 14:51 Uhr
Hallo Thomas, erstmal WOW und ein aufrichtiges Dankeschön für die schnelle Antwort.
Wenn ich das Skript so ausführe kommt bei mir folgendes.

Liegt das an meinem neuen Rechner? Entschuldige bitte da meine Erfahrungen in Powershell wie gesagt erst starten.


Drücke ich daraufhin [ENTER] wird mir eine Pfusch_neu.csv erstellt, jedoch nur mitr dem Inhalt "Lenght 1"
Bitte warten ..
Mitglied: TK1987
15.04.2021, aktualisiert um 15:00 Uhr
Wie genau hast du das Skript ausgeführt?

Geht am einfachsten so:
1) Datei als .ps1-Datei abspeichern.
2) Von der Datei eine Verknüpfung machen (Rechtsklick > kopieren und dann Rechtsklick > Verknüpfung einfügen)
3) In den Verknüpfungseigenschaften sollte bei "Ziel" bereits der Pfad zum ps1-Skript stehen. Vor diesem musst du noch powershell -EP ByPass -File ergänzen. Vollständig sollte die Zeile dann so aussehen:
Falls das Konsolenfenster auch nach Beenden des Skripts geöffnet bleiben soll, ergänzt man zusätzlich noch -NoExit
Ausgeführt wird dann immer die Verknüpfung

Zitat von @Hacktrist:
Das ist aber nicht das Skript, welches ich gepostet habe.

Die ExcecutionPolicy setzt man einmalig über folgenden Befehl...

... entweder global für alle Benutzer (Powershell muss mit Administratorrechten gestartet werden):
... oder nur für den aktuell angemeldeten Benutzer:

Wenn man die ExcecutionPolicy gesetzt hat, kann man bei der Verknüpfung das -EP ByPass weglassen.
Bitte warten ..
Mitglied: Doskias
15.04.2021 um 15:08 Uhr
Moin
Wenn man die ExcecutionPolicy gesetzt hat, kann man bei der Verknüpfung das -EP ByPass weglassen.

Aber Achtung es gibt 5 verschiedene Executions-Policies. Je nachdem wie du dein Skript ausführst, greift ggf. eine andere:


Gruß
Doskias
Bitte warten ..
Mitglied: Hacktrist
15.04.2021 um 15:16 Uhr
Es erscheint folgendes:


Bitte warten ..
Mitglied: Doskias
15.04.2021 um 15:20 Uhr
Dann fehlt ein Parameter. Wie sieht denn der Befehl aus, den du eingegeben hast?
Bitte warten ..
Mitglied: TK1987
15.04.2021, aktualisiert um 15:23 Uhr
Dann warst du zu flott beim kopieren, hatte meinen Kommentar oben noch nachträglich angepasst (Zeile 3) 😁.
Bitte warten ..
Mitglied: Hacktrist
15.04.2021, aktualisiert um 15:34 Uhr
:-) face-smile Du hast recht, das $CSV am Anfang hatte gefehlt. Hätte mir aber auch auffallen können.

Meine Ursprüngliche CSV Datei hat jedoch keinen Header. Wenn ich jetzt in Zeile 1 Schaue wird ja jede Spalte mit 1, 2, 3, 4, 5, 6 gekennzeichnet.
Können wir das entfallen lassen, so dass die csv direkt mit dem Ursprünglichen Werten beginnt (ohne Header)?

Ich habe schon versucht das
wegzulassen, was jedoch nicht funktioniert. Da läuft es auf Fehler und die Datei ist leer.
Bitte warten ..
Mitglied: TK1987
LÖSUNG 15.04.2021 um 15:37 Uhr
Zitat von @Hacktrist:
Meine Ursprüngliche CSV Datei hat jedoch keinen Header.
Richtig, hätte ich auch selbst drauf kommen können,sorry:

Bitte warten ..
Mitglied: Hacktrist
15.04.2021 um 15:45 Uhr
Thomas: Vielen Lieben Dank.

Vielleicht beschreibst Du mir noch kurz die genauen Dinge welche in Zeile 3 und 4 bei den Befehlen genau getan werden. Also als Kommentare, damit ich es auch verstehe und nicht nur copy paste nutze.
Bitte warten ..
Mitglied: TK1987
LÖSUNG 15.04.2021, aktualisiert um 17:37 Uhr
Vielleicht beschreibst Du mir noch kurz die genauen Dinge welche in Zeile 3 und 4 bei den Befehlen genau getan werden.
Der Befehl oben soll Zeile 3 eigentlich ersetzen - es gibt also keine Zeile 4.

Vielleicht fangen wir mal besser ganz vorne an...

Warum Import-CSV statt Get-Content?
Get-Content liest eine Datei als Text-Datei ein. Import-CSV hingegen wandelt die CSV-Datei in ein Objekt um, mit den Spalten als Eigenschaften.

Zum besseren Verständnis, die einzelnen Befehlszeilen einfach mal in Powershell ausführen und sich den Inhalt der Variable anzeigen lassen:
als Ausgabe bekommst du sowas:
Hinweis: Lass dich nicht verunsichern, falls das Objekt bei dir als Liste angezeigt wird. Je nach Fenstergröße wechselt Powershell bei mehreren Spalten irgendwann zur Listenanzeige.
Möchte man explizit eine bestimmte Anzeige, kann man das Objekt einfach in Format-Table bzw. Format-List pipen.

Der Vorteil eines Objekt, liegt darin, das wir nun die Zeilen, Spalten und Zellen unserer Tabelle einzeln ansprechen können:

Zeile 2
Sollte denke ich selbsterklärend sein. Für jede Zeile unseres Objekts ersetzen wir die Spalte mit dem Header "2" mit einer leeren Zeichenkette.

Nun zu deinem Problem von eben:
Ich habe schon versucht das
wegzulassen, was jedoch nicht funktioniert. Da läuft es auf Fehler und die Datei ist leer.
Wenn du den Header-Parameter bei Import-CSV weglässt, geht Powershell davon aus, dass in Zeile 1 deiner CSV-Datei Spaltenüberschriften stehen - und nimmt diese dann als Header.

Wenn deine CSV-Datei also z.B. so aussähe:
könntest du anschließend z.B. mit
die Spalte mit den Nachnamen aufrufen.

In deinem Fall führt das zu einem Fehler, da jede Spalte einen eindeutigen Namen haben muss. Zudem können wir dann natürlich nicht mehr die Spalte mit dem Namen "2" aufrufen, da es diese nicht gibt.

Die Ausgabe...
Export-CSV Wandelt unser Objekt wieder in eine Textdatei in CSV-Formatierung um; und speichert diese ab - allerdings immer mit Überschriften.
ConvertTo-CSV wandelt das Objekt genauso um, jedoch ohne es abzuspeichern. Führe nur folgendes aus:
Als Ergebnis erhälst du wieder deine Datei - auch hier derzeit noch mit Header. Hier kommt Select-Object ins Spiel, welches mit dem Parameter -Skip 1 die erste Zeile überspringt. Mit Set-Content wird die Datei dann abgespeichert.

Wir könnten die Schritte natürlich auch einzeln ausführen:

Zur Vervollständigung:
Prinzipiell könnten wir natürlich auch - wie du es vor hattest - mit Get-Content arbeiten und wie mit sed einen regex-replace machen:
oder als Einzeiler:

Bitte warten ..
Mitglied: Hacktrist
15.04.2021 um 21:21 Uhr
Du bist der Beste.
Ich habe es verstanden. Danke.
Bitte warten ..
Mitglied: Hacktrist
16.04.2021 um 08:08 Uhr
Ich habe doch noch 1 Problem. Und zwar wenn ich das Skript über die CSV laufen lasse, sind plötlich alle Einträge mit "" gekennzeichnet.
Auch die leeren Spalten sind nun mit den Gänsefüßchen eingetragen.

Kann man das ändern?
Bitte warten ..
Mitglied: TK1987
LÖSUNG 16.04.2021 um 08:48 Uhr
Zitat von @Hacktrist:

Ich habe doch noch 1 Problem. Und zwar wenn ich das Skript über die CSV laufen lasse, sind plötzlich alle Einträge mit "" gekennzeichnet.
Jo, das entspricht allerdings auch dem Dateiaufbau des CSV-Formats, wird bei der Verwendung von Sonderzeichen sogar zwingend erforderlich.
Kann man das ändern?
Mit Regex kann man alles 😉
    • sc ist ein Alias für Set-Content
    • select ist ein Alias für Select-Object
Bitte warten ..
Mitglied: Hacktrist
16.04.2021 um 08:55 Uhr
Du bist der Beste
Bitte warten ..
Mitglied: Hacktrist
19.04.2021, aktualisiert um 08:31 Uhr
Hey Thomas,

ich habe wirklich lange gesucht, aber im NEtz nicht gefunden.

Wie gehe ich denn vor, um z.B. den Pfad C:\ErstePSErfahrung\ durch eine manuelle eingabe zu ersetzen?
Also so dass das Skript ausgeführt wird, dann der Order manuell eingegeben wird und zusätzlich noch das \Pfusch1.csv angehängt wird.

Gruß
Tristan
Bitte warten ..
Mitglied: TK1987
19.04.2021, aktualisiert um 08:57 Uhr
Moin,

das ginge mit Read-Host
anschließend mit Test-Path überprüfen, ob der Ordner existiert.

... oder man nutzt den grafischen Dialog:

Gruß Thomas
Bitte warten ..
Mitglied: Hacktrist
19.04.2021, aktualisiert um 09:27 Uhr
O.k.
Und wie übergebe ich den $Ordner in den Import + Datei.csv? (hier Zeile 3)
Ich habs mal einfach mit -Path '$Ordner\datei.csv' versucht. Da crasht er aber.



Bitte warten ..
Mitglied: TK1987
19.04.2021, aktualisiert um 09:40 Uhr
Zitat von @Hacktrist:
O.k.
Und wie übergebe ich den $Ordner in den Import + Datei.csv? (hier Zeile 3)
Ich habs mal einfach mit -Path '$Ordner\datei.csv' versucht. Da crasht er aber.
Mit Single-Quotes übergibt er die Zeichenkette exakt so wie sie ist, also inklusive Dollarzeichen, ohne die Variable aufzulösen. Damit die Variable interpretiert wird, musst du Double-Quotes verwenden.

Um das gleich vorweg zu nehmen: So werden nur Variablen selbst interpretiert, nicht aber Eigenschaften eines Objekts.
Wenn du z.B. den Ordnernamen auch aus einer CSV-Datei holst, musst du, um Eigenschaften ebenfalls auszuwerten, mit $() arbeiten (solltest du ja bereits von Bash kennen). Beispiel:

Bitte warten ..
Mitglied: Hacktrist
19.04.2021, aktualisiert um 10:03 Uhr
Ich Habs raus gefunden. Der $Ordner muss direkt hinter -Path angegeben werden.


Aber das mit den Doppelquotes würde auch funktionieren, ja.

Danke Thomas
Bitte warten ..
Mitglied: Hacktrist
19.04.2021 um 11:16 Uhr
Thomas kannst du mir als letztes noch zeigen wie ich direkt die Datei inkusive Ordnerangabe (durch manuelle Pfadangabe) lade und diese Datei dann mit der Endung _neu.csv in den gleichen Ordner speichern lasse?
Bitte warten ..
Mitglied: TK1987
LÖSUNG 19.04.2021, aktualisiert um 13:47 Uhr
Zitat von @Hacktrist:
Thomas kannst du mir als letztes noch zeigen wie ich direkt die Datei inkusive Ordnerangabe (durch manuelle Pfadangabe) lade
Wenn ich das richtig verstehe, also mit kompletter Dateipfad-Eingabe?

Die Sinnhaftigkeit stelle ich hier allerdings mal infrage. Sowas würde ich...
  • entweder, wie oben erwähnt, über einen grafischen Dialog lösen
  • oder über ein Kontextmenüeintrag. So bräuchtest du nur im Explorer auf eine CSV-Datei rechtsklicken und könntest diese Datei über einen Eintrag direkt an das Skript senden.
Bitte warten ..
Mitglied: Hacktrist
20.04.2021 um 14:03 Uhr
Hey Thomas, das mit der graphischen Oberfläche ist ja cool. Habe bisher noch nicht gewusst, dass Power Shell so mächtig ist.
Nur Interesse halber, wie kann ich das geladene Objekt an den Rest des Scripts übergeben?

In Linux würde ich einfach das Objekt wie folgt übergeben und dann die beiden Skripte verbinden.
$Open=$CSV (Zeile 16)

Aber ich vermute mal das ist totaler Quatsch!?!


Bitte warten ..
Mitglied: TK1987
20.04.2021, aktualisiert um 14:38 Uhr
Zitat von @Hacktrist:
Hey Thomas, das mit der graphischen Oberfläche ist ja cool. Habe bisher noch nicht gewusst, dass Power Shell so mächtig ist.
Noch viel mächtiger, als du derzeit ahnst 😎. Auch das erstellen komplett eigener GUI-Oberflächen für ein Skript ist ganz leicht möglich.

Nur Interesse halber, wie kann ich das geladene Objekt an den Rest des Scripts übergeben?
Zu dem Zweck war das mit dem Ergebnis anzeigen gedacht. Also einfach:

Beachte allerdings, das es auch möglich ist, das der User das Öffnen der CSV-Datei abbricht, ohne eine Datei ausgewählt zu haben.
Alle weiteren Schritte würden dann natürlich zu einem Fehler führen - um das auszuschließen, einfach vorweg:
Falls die Filename-Eigenschaft leer ist, wird das Skript so automatisch beendet.
Bitte warten ..
Mitglied: Hacktrist
20.04.2021 um 14:39 Uhr
Es hängt jetzt in Zeile 23 oder 26 mit dem Fehler Der Zugriff auf den Pfad "C:\_neu" wurde verweigert


Bitte warten ..
Mitglied: TK1987
LÖSUNG 20.04.2021, aktualisiert um 17:07 Uhr
Zitat von @Hacktrist:
Es hängt jetzt in Zeile 23 oder 26 mit dem Fehler Der Zugriff auf den Pfad "C:\_neu" wurde verweigert
Das Objekt in deiner $Open-Variable enthält auch keine Eigenschaft wie DirectoryName,BaseName oder Extension.

Deshalb sagte ich, guck dir am besten immer in Powershell den Inhalt deiner Variable an.

In den meisten Fällen reicht es, einfach den Variablennamen auszuführen:

gibt dir dann folgende Ausgabe zurück:

Das sind die Eigenschaften, die dein Objekt besitzt.

Hier bringt uns in dem Fall also lediglich die Filename-Eigenschaft weiter (oder die Filenames-Eigenschaft, wenn du vor dem starten des Dialogs die Multiselect-Eigenschaft auf $true setzt, um auch mehrere Dateien gleichzeitig auswählen zu können).

Nun sehen wir uns mal an, welcher Typ in der Eigenschaft Filename liegt:
gibt folgende Ausgabe:

Die Eigenschaft ist nur vom Typ [string], also liegt der Pfad hier lediglich als Zeichenkette vor, nicht als Objekt mit Eigenschaften.

Also laden wir die Datei aus dem Dateisystem:
In dem Fall reicht ein einfaches aufrufen des Variablennamen nicht, um dir alle Eigenschaften anzeigen zu lassen.
Da ein Dateisystemobjekt recht viele Eigenschaften besitzt, wurden einige der Übersichtlichkeit halber ausgeblendet.

Man kann entweder mit Get-Member die Eigenschaften,Events und Methoden anzeigen lassen, die ein Objekt besitzt (allerdings nicht den Wert zu einer Eigenschaft)

oder man verwendet wieder Select-Object, diesmal mit dem Parameter -Property *
So werden alle Eigenschaften angezeigt, die nützlich sein könnten. Die Ausgabe zeigt hier

Wie man sieht besitzt unser Objekt nun sowohl die Eigenschaft DirectoryName mit dem DateiPfad, sowie BaseName mit dem Dateinamen ohne Erweiterung, als auch Extension mit der Dateierweiterung.

Daher:

Du solltest wirklich mal den Anfängerleitfaden durchgehen, den ich oben gepostet habe. Da wird das alles noch viel verständlicher erklärt, als ich das hier mal eben runterbeten könnte.
Bitte warten ..
Mitglied: Hacktrist
21.04.2021 um 06:53 Uhr
O.k. Ich mache mich sofort an den Leitfaden von oben.

Danke
Bitte warten ..
Mitglied: Hacktrist
21.04.2021 um 08:40 Uhr
Hier nochmal die Lösung für Alle, die im Forum auf das gleiche Problem stoßen.

Sinn und Zweck des Codes ist es eine CSV Datei öffnen zu lassen, eine Spalte zu leeren und die Datei im gleichen Ordner wieder mit der Endung _neu.csv zu speichern.

Ein rießen Dank geht raus an @TK1987


Bitte warten ..
Heiß diskutierte Inhalte
Off Topic
Aqui - Wir möchten den Hasen zurück
NixVerstehenVor 22 StundenAllgemeinOff Topic35 Kommentare

Lieber aqui, ich finde es sehr sehr schade, das du dich hier so überraschend abgemeldet hast. Ich habe auch von dir sehr viel gelernt ...

Netzwerke
Erfahrungen mit HPE Aruba Switches (Aruba OS)
sixofeightVor 1 TagAllgemeinNetzwerke13 Kommentare

Holla zusammen, Wer von euch setzt Aruba Switches (Aruba OS, ehemals HP ProCurve) ein und wie sind eure Erfahrungen bzw. wie zufrieden seid ihr ...

Webentwicklung
Webdesigner ist verschwunden
Janno100Vor 1 TagFrageWebentwicklung4 Kommentare

Hallo zusammen Kunde hat einen Webdesigner der die Domain des Kunden vor einigen Jahren einfach unter seinen eigenen Name weiter geführt hat. Diese haben ...

Exchange Server
Exchange weist Mails ohne Log Eintrag ab
Mr.RobotVor 13 StundenFrageExchange Server16 Kommentare

Guten Morgen, wir haben seit letzter Woche ein ganz spannendes "Problem" oder sollte ich eher Phänomen sagen? Wir haben eine Tochtergesellschaft die allerdings IT-Technisch ...

Windows 10
Was ist zu wenig
ukulele-7Vor 9 StundenFrageWindows 1013 Kommentare

Hallo, ich suche nach einer Quelle um Windows 10 Pro OEM Lizenzen zu beziehen, gerne auch erstmal ein paar als Testkauf. Nun ist das ...

Windows Server
Server clonen
oGutITVor 1 TagFrageWindows Server5 Kommentare

Hallo ich habe einen alten HP Server Gen8 und möchte diese auf einen HP Microserver Gen8 klonen. Auf dem HP Server ist 2W12KR2 am ...

Netzwerke
2 fritzen mit unterschiedlichen subnetzen einrichten
gelöst alpi972Vor 1 TagFrageNetzwerke7 Kommentare

Hallo, hoffe ich habs unters richtige thema gesetzt, ich habe 2 fritzboxen (eine 7490 als DSL Modem und eine 7430 als Brige), und will ...

Router & Routing
Windows Netzwerklaufwerke durch kaskadiertes Netzwerk nicht ansprechbar
TomAustriaVor 1 TagFrageRouter & Routing5 Kommentare

Hallo, wir hatten bisher nur ein "einfaches" Netzwerk und möchten dieses nun in getrennte Netzwerksegmente aufteilen: Das Netz 192.168.2.x haben wir beim AX1500 an ...