当文件包含多行数据且没有 header 时,如何计算 CSV 列数
How can I count the number of CSV columns when the file has multiline data and no header
我的 CSV 文件没有 header 和这样的多行条目:
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
添加 header 参数会使计数发生偏差。
(Import-Csv .\bad.csv -Delimiter ";" -Header (1..99) | get-member -type NoteProperty).count
我不得不通过 Get-Content 手动中止读取文件,因为我必须手动处理所有解析。转义字符和多行条目...
我的 PowerShell 版本是 3,稍后我必须将我的脚本移植到版本 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",'') -split "`r`n" | Select -First 1).split($delimiter)).Count
$fileData | ConvertFrom-Csv -Header (1..$numberOfColumns) -Delimiter $delimiter
这将做的是找到以双引号结尾的行,后跟不包含定界符的数据。我们还匹配后面的换行符,但在替换中删除相同的换行符。如果这样做了,我们就知道第一行是正确的。像以前一样使用同一行进行拆分和计数。
既然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 这样做需要太多代码)
我知道这已经很老了,但我今天遇到了类似的情况(没有不同列的行)并找到了我自己的解决方案,所以我想我会与遇到这种情况的其他人分享。我的解决方案是对 CSV 的第一行使用 Get-Content 并在分隔符 (,) 上使用 -split 来创建数组,然后使用 return 数组的计数。如上面的回复所述,这将不考虑引号中存在的分隔符。
((Get-Content $PathToCsv)[0] -split ",").count
我的 CSV 文件没有 header 和这样的多行条目:
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
添加 header 参数会使计数发生偏差。
(Import-Csv .\bad.csv -Delimiter ";" -Header (1..99) | get-member -type NoteProperty).count
我不得不通过 Get-Content 手动中止读取文件,因为我必须手动处理所有解析。转义字符和多行条目...
我的 PowerShell 版本是 3,稍后我必须将我的脚本移植到版本 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",'') -split "`r`n" | Select -First 1).split($delimiter)).Count
$fileData | ConvertFrom-Csv -Header (1..$numberOfColumns) -Delimiter $delimiter
这将做的是找到以双引号结尾的行,后跟不包含定界符的数据。我们还匹配后面的换行符,但在替换中删除相同的换行符。如果这样做了,我们就知道第一行是正确的。像以前一样使用同一行进行拆分和计数。
既然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 这样做需要太多代码)
我知道这已经很老了,但我今天遇到了类似的情况(没有不同列的行)并找到了我自己的解决方案,所以我想我会与遇到这种情况的其他人分享。我的解决方案是对 CSV 的第一行使用 Get-Content 并在分隔符 (,) 上使用 -split 来创建数组,然后使用 return 数组的计数。如上面的回复所述,这将不考虑引号中存在的分隔符。
((Get-Content $PathToCsv)[0] -split ",").count