Benutzer mit den meisten Antworten
Mit Inhalten/Werten einer CSV Datei rechnen

Frage
-
Hallo Experten!
Ich habe erfolgreich eine CSV Datei importiert die mehrere Spalten enthält. Unter anderem eine Spalte mit GB die jedoch mit dem Wert 100 zu multiplizieren ist. Wie stelle ich das an?
Habe bisher die Werte der Spalten MID (Maschinen ID) und GB TSM Storage in Arrays gespeichert
ForEach-Object { $MID += $_.MID $GBTSM +=$_.'GB TSM Storage' }
diese werden auch ordentlich ausgegeben. Nur, wie rechne ich jetzt mit dem Inhalt der $GBTSM Spalte? Woher weiss Powershell überhaupt, dass es sich um Zahlen und nicht um Strings handelt bzw. wie sage ich ihm das? Bin leider total planlos
danke für eure Hilfe!
lg
tchintchie
Antworten
-
$csv = @() $csv = Import-Csv "file.csv" -Delimiter ";" # hier versuchst du die CSV Spalte in einen double Typ umzuwandeln # (was ja schief geht weil das deutsche komma benutzt wird) # Da in $CSV eine Liste (Array) von mehreren Objekten ist ist der Typ der Liste Objekt[] # Ebenso ist $GBTSM eine Liste mit mehreren Objekten; also ein Arra vom Typ Objekt[] in dem sich viele Objekte befinden [double]$GBTSM= $csv | Where-Object{$_.'GB TSM Storage'} # ForEach-Object holt jedes Objekt einzeln aus der Objekt[] Liste (Array) $GBTSM | ForEach-Object{ # Das einzelne objekt das gerade von ForEach-Object hier weitergegeben wird # ist in der Variablen $_ gespeichert nicht in der Variablen $GBTSM ! # Hier versuchst du die gesammte Liste $GBTSM auf einmal zu berarbeiten. Das geht nicht! $GBTSM.replace(',','.') # so wäre es richtig, hier wird das einzelne Objekt aus der Liste bearbeitet $_.replace(',','.') # das geht aber schief weil du oben gesagt hast das die Objekte alle den typ [double] haben sollen # double ist keine string und hat die Methode replace() nicht! } $GBTSM.GetType() #$csv | Sort-Object MID | Format-Table MID, 'GB TSM Storage' -AutoSize
---------------------------------------------------------------
# Nimm bitte statt der Methode GetType() das Cmdlet Get-Member # in einer Importierten CSV Datei sind alle Daten schon vom Typ String (NoteProperty = String)! # nur String Objekte haben die Methode Replace() # die Objekt die eine CSV Produziert analysieren NoteProperty = String ! Import-Csv "file.csv" -Delimiter ";" | Get-Member Read-Host "Schau dir die ausgabe von Get-Member in ruhe an. `n`nWeiter mit der Taste Enter" # Ein einzelnes Property analysieren es ist ein String! # Nur ein String hat die Methode Replace $csv = Import-Csv "file.csv" -Delimiter ";" $csv.'GB TSM Storage' | Get-Member Read-Host "Schau dir die ausgabe von Get-Member in ruhe an. `n`nWeiter mit der Taste Enter"
---------------------------
So ist es richtig:
Import-Csv "file.csv" -Delimiter ";" | ForEach-Object{ # Das einzelne objekt das gerade von ForEach-Object hier weitergegeben wird # ist in der Variablen $_ gespeichert # wir rufen von das 'GB TSM Storage' Property (Spalte in der CSV) von dem Objekt $_ ab $GBTSM = $_.'GB TSM Storage' # das Property ist vom Typ String wie wir oben gesehen habe # nun können wir die Methode replace nutzen um das Komma durch einen Punk zu ersetzen $GBTSM = $GBTSM.replace(',','.') # jetzt kann PowerShell $GBTSM in eine Zahl umwandeln 100 * $GBTSM }
---------------------------
So kann man es kurz machen:
# Klammern () geben die reihenfolge vor wie PowerShell Arbeitet! ForEach($CsvObject in (Import-Csv "D:\Temp\Processes.csv" -Delimiter ";")) { # (auslesen des Property 'GB TSM Storage') # darauf wird die Methode replace() angewendet 100 * ($CsvObject.'GB TSM Storage').replace(',','.') }
Please click “Mark as Answer” if my post answers your question and click “Vote As Helpful” if my Post helps you.
Bitte markiere hilfreiche Beiträge von mir als “Als Hilfreich bewerten” und Beiträge die deine Frage ganz oder teilweise beantwortet haben als “Als Antwort markieren”.
My PowerShell Blog http://www.admin-source.info
[string](0..21|%{[char][int]([int]("{0:d}" -f 0x28)+('755964655967-86965747271757624-8796158066061').substring(($_*2),2))})-replace' '
German ? Come to German PowerShell Forum!- Bearbeitet Peter Kriegel Mittwoch, 21. August 2013 07:46 asasd
- Als Antwort markiert tchintchie Mittwoch, 21. August 2013 08:21
Alle Antworten
-
Hallo,
die Powershell ist sehr gnaedig und versucht zu erraten was du willst. :-)Also zb: das geht
$a = "Hallo" + 5
das nicht
$a = 5 + "Hallo"
Der Parser orientiert sich am ersten Wert nach dem = , im ersten Fall also ein String der Hallo entahelt, also haengt er einfach die 5 dran, was Hallo5 macht , im 2. Fall versucht er 5 mit Hallo zu addieren, was nicht geht, weil Hallo keine Zahl ist.
Du kannst in [] vor dem Namen schreiben was du willst.
[string]$b
Was sich hinter der Variablen verbirgt kannst Du z.B. so feststellen
$b | Get-Member
Hier noch ein Link zu dem Thema:
http://technet.microsoft.com/de-de/magazine/2007.03.powershell.aspxBest regards
brima- Bearbeitet brima Montag, 19. August 2013 14:14
-
Hallo!
danke für die Antwort. Ja, das mit den flexiblen Variablen hab ich schon gewusst. Nur, wie wende ich das jetzt konkret in meinem Fall an? Ich möchte alle Werte, die in dem Array $GBTSM stehen mit 100 multiplizieren.
$GBTSM | ForEach-Object{ $GBTSM*100 }
Obiger Code brachte leider nicht das gewünschte Ergebnis (sondern listet nur alles 100 mal auf...) Brauche ich ein neues Array? Wie spreche ich die Werte in der Spalte an? Stehe voll auf der Leitung.
lg
tchintchie
-
Hallo tchintchie
Anscheinend hast du nicht verstanden was Brima dir sagen möchte.
Hier muss man darauf achten was für einen Typ eine Variable enthält.
Den Typ den eine Variabel gerade enthält bekommt man mit Get-Member oder mit der Methode GetType() heraus.Die Zahl 345 kann man als Typ Text = String "345" oder als Typ Zahl = Integer 345 in einer Variablen finden.
Wenn man einen String hat wie bei dir, dann wird einfach nur der String 100 mal angezeigt.
Deshalb muss man PowerShell sagen das der String in eine Integer Zahl umgewandelt werden soll.
Dazu benutzt man die Typ Acceleratoren in den Eckigen klammern.
[datetime] Datum oder Zeit [string] Zeichenfolge [char] Einzelnes Zeichen [double] Gleitzahl mit doppelter Genauigkeit [single] Gleitzahl mit einfacher Genauigkeit [int] 32-Bit ganze Zahl [wmi] Windows Management Instrumentation (WMI) Instanz oder Sammlung [adsi] Active Directory-Dienstobjekt [wmiclass] WMI-Klasse [Boolesch] Wahrer oder Falscher Wert Der Trick ist, wie Brima schon sagte,das PowerShell immer Typ des ersten Wert nimmt und versucht den zweiten Wert in einen passenden Typ umzuwandeln.
# dies Funktioniert ohne Typ umwandlung, # da der erste wert eine Zahl, ist wird der String auch in eine Zahl umgewandelt! $GBTSM | ForEach-Object{ 100 * $GBTSM } # dies Funktioniert nur mit Typ umwandlung [Int] ! $GBTSM | ForEach-Object{ [Int]$GBTSM * 100 }
Please click “Mark as Answer” if my post answers your question and click “Vote As Helpful” if my Post helps you.
Bitte markiere hilfreiche Beiträge von mir als “Als Hilfreich bewerten” und Beiträge die deine Frage ganz oder teilweise beantwortet haben als “Als Antwort markieren”.
My PowerShell Blog http://www.admin-source.info
[string](0..21|%{[char][int]([int]("{0:d}" -f 0x28)+('755964655967-86965747271757624-8796158066061').substring(($_*2),2))})-replace' '
German ? Come to German PowerShell Forum!- Bearbeitet Peter Kriegel Dienstag, 20. August 2013 07:36 asdsd
-
Hallo Peter!
Danke für den Hinweis. Glaub jetzt hab ichs kapiert und es würde prinzipiell sogar funktionieren ... aber mein $GBTSM Array lässt sich nicht in einen int oder double (die Werte sind nämlich Kommazahlen) umwandeln. Bekomme folgenden Fehler (übrigens auch bei int):
Der Wert "System.Object[]" vom Typ "System.Object[]" kann nicht in den Typ "System.Double" konvertiert werden. In H:\Documents\PowerShell\xls.ps1:35 Zeichen:5 + [double]$GBTSM*100 + ~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidArgument: (:) [], RuntimeException + FullyQualifiedErrorId : ConvertToFinalInvalidCastException
Wenn ich die 100 vorn anstelle schaut die Fehlermeldung so aus:
Fehler beim Aufrufen der Methode, da [System.Object[]] keine Methode mit dem Namen "op_Multiply" enthält. In H:\Documents\PowerShell\xls.ps1:35 Zeichen:5 + 100*$GBTSM + ~~~~~~~~~~ + CategoryInfo : InvalidOperation: (op_Multiply:String) [], RuntimeException + FullyQualifiedErrorId : MethodNotFound
Laut diesem Tutorial www msxfaq de/code/powershell/pscsv htm sollte es eigentlich klappen...allerdings habe ich mein Import-Csv einer Variablen zugewiesen und nicht einem Array...aber die Spalte $GBTSM wäre eigentlich als Array definiert trotzdem bekomme ich den System.Object Error :-/
$CSV = Import-Csv "file.csv" -Delimiter ";" | ForEach-Object { $MID += $_.MID $GBTSM +=$_.'GB TSM Storage' }
das hab ich aus einem anderen Tutorial...ist das überhaupt notwendig?
-
Poste bitte mal deine CSV Daten.
Es reicht wen du die Kopfzeile mit den Spalten überschriften und die erste Datenzeile postes. Sensible Personen oder Firmen Daten musst du natürlich maskieren!
Please click “Mark as Answer” if my post answers your question and click “Vote As Helpful” if my Post helps you.
Bitte markiere hilfreiche Beiträge von mir als “Als Hilfreich bewerten” und Beiträge die deine Frage ganz oder teilweise beantwortet haben als “Als Antwort markieren”.
My PowerShell Blog http://www.admin-source.info
[string](0..21|%{[char][int]([int]("{0:d}" -f 0x28)+('755964655967-86965747271757624-8796158066061').substring(($_*2),2))})-replace' '
German ? Come to German PowerShell Forum!- Bearbeitet Peter Kriegel Dienstag, 20. August 2013 08:26 ghfghfgh
-
MID;Serien-Nr.;Servertyp;Ansprechpartner;Beschreibung;H,B,p,s,V;Produkt;seit Datum;€ / Monat v2.2 bis Q2;€ / Monat v2.3 ab Q3;M.;€/Quartal;Kat.;CPU;Cores TSM;Cores REST;GB RAM;146 GB HDD;300 GB HDD;600 GB HDD;900 GB HDD;Mtl. Zusatz;SAN Anbdg.;SAN VIE;SAN VIE gesp.;SAN ungesp.;SAN gesp.;;GB TSM Storage;ZGI;BS;Image;Erw. Betr.;7x24;R-Wartung
C870000C;TEST-EINTRAG zum PROBIEREN;;;;;;;522,80;420,00;3;1.260,00;C;1;6;6;32,0;0;;;;;;;;;;;0,0;0;W2003;0;;;
sorry für diese Unübersichtlichkeit...habe hier keine Möglichkeit gefunden Tabellen zu erstellen und Dateien kann ich leider (noch) keine mit anhängen :-/ Sollte aber zum Testen importierbar sein
danke für die Mühe
-
Du hast das aus Excel exportiert!?
Die Spaltenüberschriften sind nich CSV kompatibel. Leerzeichen in spalten Namen sind nicht erlaubt und die anderen Sonderzeichen können auch Ärger machen.
Excel Exportiert leider keine sauberen CSV Daten (mit Anführungszeichen) siehe hier :
http://superuser.com/questions/130592/how-do-you-force-excel-to-quote-all-columns-of-a-csv-file
http://www.markinns.com/articles/full/export_excel_csvs_with_double_quotes
Deshalb generiert Import-CSV immer eine Fehler bei mir !
Please click “Mark as Answer” if my post answers your question and click “Vote As Helpful” if my Post helps you.
Bitte markiere hilfreiche Beiträge von mir als “Als Hilfreich bewerten” und Beiträge die deine Frage ganz oder teilweise beantwortet haben als “Als Antwort markieren”.
My PowerShell Blog http://www.admin-source.info
[string](0..21|%{[char][int]([int]("{0:d}" -f 0x28)+('755964655967-86965747271757624-8796158066061').substring(($_*2),2))})-replace' '
German ? Come to German PowerShell Forum!- Bearbeitet Peter Kriegel Dienstag, 20. August 2013 09:13 asdasd
-
Hallo,
ein Problem ist, dass die Powershell intern mit dem Punkt arbeitet als Trenner und nicht wie hier ueblich mit dem Komma.
Hier einfach mal ein paar Beispiele, wie sich . bzw. , so auswirken.
Beste Gruesse
brimaPS U:\> $a = 420,75
PS U:\> $a
420
75
PS U:\> $a.GetType()IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array##########
PS U:\> $a = 420.75
PS U:\> $a
420,75
PS U:\> $a.GetType()IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Double System.ValueType##########
PS U:\> $a = "420,75".Replace(',','.')
PS U:\> $a
420.75
PS U:\> $a.GetType()IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object##########
PS U:\> [double]$a = "420,75"
PS U:\> $a
42075
PS U:\> $a.GetType()IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Double System.ValueType##########
PS U:\> [double]$a = "420,75".Replace(',','.')
PS U:\> $a
420,75
PS U:\> $a.GetType()IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Double System.ValueType -
Ja, die Originalquelldatei ist eine .xlsx (leider). Habe den Export in CSV auch über Powershell mit dem Excel ComObject erledigt. Die Spaltenüberschriften und Leerzeichen sind nicht so das Problem (mit "" bekommt er das in den Griff). Aber wie ich mir bereits dachte rechnet Powershell mit dem "." und nicht mit "," als Kommatrennzeichen. Werde jetzt die .Replace Methode probieren
vielen Dank für Eure Hilfe! Melde mich wenn ich Erfolg hatte :-)
-
Guten Morgen!
Ich muss leider schon wieder lästig sein. Da der Inhalt meiner Variable ein System.Object ist kann ich darauf weder die .Replace Methode anwenden noch einen Typecast auf Integer bzw. Double machen um damit zu rechnen :-/
Hier noch mal mein Testcode:
$csv = @() $csv = Import-Csv "file.csv" -Delimiter ";" [double]$GBTSM=$csv |Where-Object{$_.'GB TSM Storage'} $GBTSM | ForEach-Object{ $GBTSM.replace(',','.') } $GBTSM.GetType() #$csv | Sort-Object MID | Format-Table MID, 'GB TSM Storage' -AutoSize
$GBTSM sollte eigentlich die Werte der Spalte enthalten mit denen ich rechnen will (sie müssen alle mit 100 multipliziert werden). Wenn ich die Variable oben ebenfalls als Array definiere ist sie vom Typ zwar ein Array....kann aber immer noch nicht damit rechnen. Vermutlich weil es mir statt der Spalte die ganze Zeile reinspeichert.
$GBTSM[3].GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True False PSCustomObject System.Object
In diesem Tutorialbeispiel funktioniert es (mit dem Unterschied, dass hier statt einer ganzen Spalte eben nur ein Teil selektiert wird). Aber es muss doch auch mit der ganzen Spalte klappen?
$ergebnis = $csvlist | where {$_.Name -eq "nachname4"} [int]($ergebnis[0].Alter) +=1
Wie stelle ich das denn am besten an? In weiterer Folge sollte ich nämlich diese umgewandelten/multiplizierten Werte mit denen einer anderen Spalte einer anderen Tabelle vergleichen...
Bitte entschuldigt meine Anfängerfragen, aber ich bin nun mal eine Anfängerin :-S
danke im Voraus
lg
-
$csv = @() $csv = Import-Csv "file.csv" -Delimiter ";" # hier versuchst du die CSV Spalte in einen double Typ umzuwandeln # (was ja schief geht weil das deutsche komma benutzt wird) # Da in $CSV eine Liste (Array) von mehreren Objekten ist ist der Typ der Liste Objekt[] # Ebenso ist $GBTSM eine Liste mit mehreren Objekten; also ein Arra vom Typ Objekt[] in dem sich viele Objekte befinden [double]$GBTSM= $csv | Where-Object{$_.'GB TSM Storage'} # ForEach-Object holt jedes Objekt einzeln aus der Objekt[] Liste (Array) $GBTSM | ForEach-Object{ # Das einzelne objekt das gerade von ForEach-Object hier weitergegeben wird # ist in der Variablen $_ gespeichert nicht in der Variablen $GBTSM ! # Hier versuchst du die gesammte Liste $GBTSM auf einmal zu berarbeiten. Das geht nicht! $GBTSM.replace(',','.') # so wäre es richtig, hier wird das einzelne Objekt aus der Liste bearbeitet $_.replace(',','.') # das geht aber schief weil du oben gesagt hast das die Objekte alle den typ [double] haben sollen # double ist keine string und hat die Methode replace() nicht! } $GBTSM.GetType() #$csv | Sort-Object MID | Format-Table MID, 'GB TSM Storage' -AutoSize
---------------------------------------------------------------
# Nimm bitte statt der Methode GetType() das Cmdlet Get-Member # in einer Importierten CSV Datei sind alle Daten schon vom Typ String (NoteProperty = String)! # nur String Objekte haben die Methode Replace() # die Objekt die eine CSV Produziert analysieren NoteProperty = String ! Import-Csv "file.csv" -Delimiter ";" | Get-Member Read-Host "Schau dir die ausgabe von Get-Member in ruhe an. `n`nWeiter mit der Taste Enter" # Ein einzelnes Property analysieren es ist ein String! # Nur ein String hat die Methode Replace $csv = Import-Csv "file.csv" -Delimiter ";" $csv.'GB TSM Storage' | Get-Member Read-Host "Schau dir die ausgabe von Get-Member in ruhe an. `n`nWeiter mit der Taste Enter"
---------------------------
So ist es richtig:
Import-Csv "file.csv" -Delimiter ";" | ForEach-Object{ # Das einzelne objekt das gerade von ForEach-Object hier weitergegeben wird # ist in der Variablen $_ gespeichert # wir rufen von das 'GB TSM Storage' Property (Spalte in der CSV) von dem Objekt $_ ab $GBTSM = $_.'GB TSM Storage' # das Property ist vom Typ String wie wir oben gesehen habe # nun können wir die Methode replace nutzen um das Komma durch einen Punk zu ersetzen $GBTSM = $GBTSM.replace(',','.') # jetzt kann PowerShell $GBTSM in eine Zahl umwandeln 100 * $GBTSM }
---------------------------
So kann man es kurz machen:
# Klammern () geben die reihenfolge vor wie PowerShell Arbeitet! ForEach($CsvObject in (Import-Csv "D:\Temp\Processes.csv" -Delimiter ";")) { # (auslesen des Property 'GB TSM Storage') # darauf wird die Methode replace() angewendet 100 * ($CsvObject.'GB TSM Storage').replace(',','.') }
Please click “Mark as Answer” if my post answers your question and click “Vote As Helpful” if my Post helps you.
Bitte markiere hilfreiche Beiträge von mir als “Als Hilfreich bewerten” und Beiträge die deine Frage ganz oder teilweise beantwortet haben als “Als Antwort markieren”.
My PowerShell Blog http://www.admin-source.info
[string](0..21|%{[char][int]([int]("{0:d}" -f 0x28)+('755964655967-86965747271757624-8796158066061').substring(($_*2),2))})-replace' '
German ? Come to German PowerShell Forum!- Bearbeitet Peter Kriegel Mittwoch, 21. August 2013 07:46 asasd
- Als Antwort markiert tchintchie Mittwoch, 21. August 2013 08:21
-
Ich rate dir dringend ein gutes PowerShell Buch zu lesen!
Hier meine Empfehlungen:
http://www.admin-source.de/BlogDeu/buecher-books
Ich habe auf Youtube auch einen 21 Teiligen PowerShell Kurs.
Gib dort mal "German PowerShell" ein dann kommst du auf meinen Kanal.
Please click “Mark as Answer” if my post answers your question and click “Vote As Helpful” if my Post helps you.
Bitte markiere hilfreiche Beiträge von mir als “Als Hilfreich bewerten” und Beiträge die deine Frage ganz oder teilweise beantwortet haben als “Als Antwort markieren”.
My PowerShell Blog http://www.admin-source.info
[string](0..21|%{[char][int]([int]("{0:d}" -f 0x28)+('755964655967-86965747271757624-8796158066061').substring(($_*2),2))})-replace' '
German ? Come to German PowerShell Forum! -
den Kanal werd ich gleich abbonieren danke! Problem ist nur, dass ich zuwenig Praxis habe und Scripten eigentlich nicht mein Aufgabengebiet ist (aber eben diese "kleine" Aufgabe lösen soll). Aber kann nie schaden sich etwas wissen anzueignen.
nochmal danke