2016-06-23 11 views
2

Meine CSV-Dateien haben wie diese keine Kopf- und Multi-Line-Einträge:Wie kann ich die Anzahl der CSV-Spalten zählen, wenn die Datei mehrzeilige Daten und keinen Header

11;"multi line 
col12";13;foobar;foobar 
21;22;23;24;25 

Und ich möchte die Anzahl zählen von Spalten. Also 5 in diesem Beispiel. Wie mache ich das?

Was ich versuche:

Import-CSV funktioniert nicht ohne die Header-Parameter durch Einträge duplizieren in der ersten Zeile.

(Import-Csv .\bad.csv -Delimiter ";" | get-member -type NoteProperty).count 

Durch Hinzufügen eines Header-Parameters wird die Anzahl verzerrt.

Ich musste das Lesen der Datei manuell über Get-Content abbrechen, weil ich das Parsing manuell durchführen musste. Escape-Zeichen und mehrzeilige Einträge ...

Meine Version von PowerShell ist 3 und ich muss später mein Skript auf Version 2 portieren.

+1

Wie unterscheiden Sie den Zeilenumbruch in AV Aus dem CSV-Linebreak? – sodawillow

+2

CSV-Feldnamen sollen eindeutig sein. Ich schlage vor, Sie beheben die Ursache (Ihre Eingabedaten), anstatt mit den Symptomen umzugehen. –

+0

@Matt Multi-Zeilen-CSV sind umstritten, werden aber von Import-Csv unterstützt und ich kann sie nicht vermeiden. http: //www.heikniemi.net/hardcoded/2010/01/powershell-basics-1-lesen-und-parsen-csv/ –

Antwort

2

Da Excel kennt, lassen Sie uns ihn fragen:

$path = "path\to\bad.csv" 
$excel = New-Object -ComObject Excel.Application 

$workbook = $excel.Workbooks.Open($path) 
$sheet = $workbook.ActiveSheet 

$columnIndex = 1 
while($sheet.Cells.Item(1, $columnIndex).Text -ne "") { 
    $columnIndex++ 
} 

"There are $($columnIndex - 1) columns in CSV file $path" 

Start-Sleep -Seconds 1 
Get-Process excel | Stop-Process -Force 

Wie Ansgar Wiechers in Kommentaren darauf hingewiesen, gibt es eine viel kürzere Lösung:

$path = "path\to\bad.csv" 
$excel = New-Object -ComObject Excel.Application 

$workbook = $excel.Workbooks.Open($path) 
$sheet = $workbook.ActiveSheet 

$columnCount = $sheet.UsedRange.Columns.Count 
"There are $columnCount columns in CSV file $path" 

Start-Sleep -Seconds 1 
Get-Process excel | Stop-Process -Force 

(Ich weiß, dass meine Art Tötung Excel ist schmutzig, aber iirc dauert es zu viel Code zu tun)

+0

Dies ist eine gute Möglichkeit, das Problem zu beheben, wenn Excel auf dem laufenden System installiert ist. – Matt

+0

... und eine leere Zelle im Dataset = 'break' – sodawillow

+0

' $ sheet.UsedRange.Columns.Count'. Beachten Sie jedoch, dass Excel ziemlich wählerisch ist, was es als CSV akzeptiert. –

2

Wenn Sie bereit sind, den Vorbehalt zu akzeptieren, dass dies die Anzahl der Spalten falsch zählen könnte, wenn in Klammern Trennzeichen in einer Zeichenfolge enthalten sind, könnte dies gut genug für Sie sein.

$path = "c:\temp\test.txt" 
$delimiter = ";" 

$numberOfColumns = Get-Content $path | 
    ForEach-Object{($_.split($delimiter)).Count} | 
    Measure-Object -Maximum | 
    Select-Object -ExpandProperty Maximum 

Import-Csv $path -Header (1..$numberOfColumns) -Delimiter $delimiter 

Lesen in der Datei mit Get-Content und die maximale Anzahl von Spalten, die durch Aufspalten jede Linie auf dem Delimiter isolieren und dann diesen Wert mit dem CSV zu importieren. Wenn die Datei groß ist, können Sie die Datei einmal mit Get-Content einlesen und dann ConvertTo-CSV verwenden, sobald Sie Ihre Spaltenanzahl kennen.


Wenn alle Zeilen einen Zeilenumbruch enthalten, würde die obige Logik fehlschlagen. Dennoch konnten wir die Daten vorübergehend bereinigen, indem wir die korrekten Zeilenumbrüche löschten, um die genaue Anzahl zu erhalten.

$delimiter = ";" 
$fileData = (Get-Content $path | Out-String) 

$numberOfColumns = ((($fileData -replace "(`"[^;]+?)`r`n",'$1') -split "`r`n" | Select -First 1).split($delimiter)).Count 

$fileData | ConvertFrom-Csv -Header (1..$numberOfColumns) -Delimiter $delimiter 

Was dies tun wird ist Zeilen finden, die am Ende, wo es ein doppeltes Anführungszeichen, gefolgt von Daten, die nicht das Trennzeichen enthalten. Wir passen auch die folgende neue Zeile an, lassen aber die gleiche neue Zeile in der Ersetzung fallen. Wenn das getan ist, wissen wir, dass die erste Zeile korrekt ist. Verwenden Sie dieselbe Zeile zum Teilen und Zählen wie zuvor.

+0

Wenn jede Zeile mindestens einen Wert mit einem Zeilenumbruch enthält, erhält der Algorithmus die Anzahl richtig? – sodawillow

+0

@sodawillow Natürlich würde das nicht funktionieren nein. Diese Möglichkeit wird aus den Stichprobendaten oder dem OP nicht deutlich. Es sollte jedoch leicht sein, diese Möglichkeit zu berücksichtigen, daher werde ich updaten. – Matt

+0

Ihre Bearbeitung ist, was ich zuerst im Sinn hatte, aber aufgehört zu versuchen, den Code herauszufinden, sobald ich über Excel lesen ^^. Sieht gut aus. Ich weiß nicht, ob das Importieren der Datei überhaupt notwendig ist:). – sodawillow