当文件具有多行数据且没有标题时,如何计算CSV列的数量

时间:2016-06-23 11:29:59

标签: powershell powershell-v2.0

我的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.

3 个答案:

答案 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