我的CSV文件没有标题和多行条目,如下所示:
11;"multi line
col12";13;foobar;foobar
21;22;23;24;25
我想计算列数。在这个例子中是5。我该怎么做?
我尝试了什么:
由于第一行上有重复的条目, Import-CSV
在没有header参数的情况下不起作用。
(Import-Csv .\bad.csv -Delimiter ";" | get-member -type NoteProperty).count
添加标题参数会使计数倾斜。
(Import-Csv .\bad.csv -Delimiter ";" -Header (1..99) | get-member -type NoteProperty).count
我不得不通过Get-Content手动中止读取文件,因为我必须手动处理所有解析。转义字符和多行条目......
我的PowerShell版本是3,我必须稍后将脚本移植到版本2.
答案 0 :(得分:2)
如果您愿意接受警告,如果字符串中有引号分隔符,这可能会错误计算列数,这对您来说可能已经足够了。
$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
使用Get-Content
读取文件并隔离最大列数
拆分其分隔符上的每一行,然后使用该值导入CSV。如果文件很大,您可以使用Get-Content
读取文件一次,然后在知道列数后使用ConvertTo-CSV
。
如果所有行都包含换行符,则上述逻辑将失败。我们仍然可以通过删除正确的换行符来暂时清理数据,以获得准确的计数。
$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
这样做的目的是找到以双引号后跟不包含分隔符的数据结束的行。我们还匹配后面的换行符,但在替换中删除了相同的新行。如果这样做,我们知道第一行是正确的。使用相同的行来分割和计数就像以前一样。
答案 1 :(得分:2)
由于Excel知道,让我们问他:
$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
正如 Ansgar Wiechers 在评论中指出的那样,有一个更短的解决方案:
$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
(我知道我杀死Excel的方式很脏,但 iirc 这样做需要太多代码)
答案 2 :(得分:0)
我知道这已经很老了,但是今天我遇到了类似的情况(没有不同行的行),并且找到了自己的解决方案,因此我想与任何其他遇到这种情况的人分享。我的解决方案是将Get-Content用于CSV的第一行,并在定界符(,)上使用-split创建一个数组,然后返回该数组的计数。如以上答复中所述,这将不考虑引号中存在的定界符。
((Get-Content $PathToCsv)[0] -split ",").count