我有一个 CSV 文件,其中在单元格中包含空行和换行符,如下所示:
Richard Roe
Mary Major
"Alex Smith
Betty Brown
Chris Clark"
"Betty Brown
Donna Davis
Edward Evans"
Alex Smith
"Richard Roe
Mary Major"
我正在尝试编写一个 PowerShell 脚本来读取此 CSV 文件并获得以下结果(在列表中插入其部门的名称):
"Legal
Richard Roe"
"Accounting
Mary Major"
"R&D
Alex Smith
Betty Brown
Design
Chris Clark"
"R&D
Betty Brown
Design
Donna Davis
Edward Evans"
"R&D
Alex Smith"
"Legal
Richard Roe
Accounting
Mary Major"
当您使用
Import-CSV
读取 CSV 文件时,它会忽略这样的空行:
PS C:\tmp> Import-Csv -Header Names .\NamesList.csv
Names
-----
Richard Roe
Mary Major
Alex Smith...
Betty Brown...
Alex Smith
Richard Roe...
PS C:\tmp>
我的期望是:
Names
-----
Richard Roe
Mary Major
Alex Smith...
Betty Brown...
Alex Smith
Richard Roe...
您可以切换到
Get-Content
来读取CSV,但单元格中的换行符似乎很难处理。
有什么办法可以防止
Import-Csv
忽略空行吗?
您实际上并不需要输入 CSV 中的空行进行处理。这只是一个视觉的东西。分组已经通过将多个名称放入单个带引号的字段中来完成。因此,只需处理输入数据,同时忽略空行并将它们添加回输出 CSV 中。
这是一个使用
ConvertFrom-Csv
和 ConvertTo-Csv
的简单可重现示例,但您可以将它们替换为 Export-
cmdlet,行为应该是相同的。
$names = ConvertFrom-Csv -Header Names @'
Richard Roe
Mary Major
"Alex Smith
Betty Brown
Chris Clark"
"Betty Brown
Donna Davis
Edward Evans"
Alex Smith
"Richard Roe
Mary Major"
'@
$departments = 'Legal', 'Accounting', 'R&D', 'R&D', 'R&D', 'LEGAL'
$namesWithDeps = foreach( $i in 0..$($names.Count - 1) ) {
# Output empty field
[PSCustomObject]@{ Names = '' }
# Join department and names
[PSCustomObject]@{ Names = $departments[$i] + [Environment]::NewLine + $names[$i].Names }
}
$namesWithDeps | ConvertTo-Csv
输出:
"Names"
""
"Legal
Richard Roe"
""
"Accounting
Mary Major"
""
"R&D
Alex Smith
Betty Brown
Chris Clark"
""
"R&D
Betty Brown
Donna Davis
Edward Evans"
""
"R&D
Alex Smith"
""
"LEGAL
Richard Roe
Mary Major"
它与您想要的输出略有不同,但语义上是相同的。
Import-Csv
没有此选项,但您可以使用 StreamReader
从文件创建对象来解决此问题。但这需要一些工作。
假设该文件看起来与您在问题中共享的完全相同,类似这种方法可能会起作用:
function Read {
param($Path, $Header)
try {
$reader = [System.IO.StreamReader] (Convert-Path $path)
$tmp = [ordered]@{}
$sb = [System.Text.StringBuilder]::new()
while ($null -ne ($line = $reader.ReadLine())) {
if ($line.StartsWith('"')) {
$sb.AppendLine($line.TrimStart('"'))
while ($true) {
$line = $reader.ReadLine()
if ($line.EndsWith('"')) {
$sb = $sb.Append($line.TrimEnd('"'))
break
}
$sb = $sb.AppendLine($line)
}
$tmp[$header] = $sb.ToString()
$sb = $sb.Clear()
}
else {
$tmp[$header] = $line
}
[pscustomobject] $tmp
$tmp.Clear()
}
}
finally {
$reader.Dispose()
}
}
$names = Read .\NamesList.csv -Header Names
$names
这将输出一组像您所期望的对象:
Names
-----
Richard Roe
Mary Major
Alex Smith…
Betty Brown…
Alex Smith
Richard Roe…
然后您可以通过按索引更新对象来添加部门。目前还不清楚这些来自哪里,如果我们有这些信息,可以提前将它们添加到前面以获得更有效的方法:
$names[1].Names = "Legal`n$($names[1].Names)"
$names[2].Names = "Accounting`n$($names[2].Names)"
$names[3].Names = "R&D`n$($names[3].Names)"
$names | ConvertTo-Csv # <= This for demo, it should be `Export-Csv` instead
然后生成的 CSV 将如您所期望的那样:
"Names"
""
"Legal
Richard Roe"
"Accounting
Mary Major"
"R&D
Alex Smith
Betty Brown
Chris Clark"
""
"Betty Brown
Donna Davis
Edward Evans"
""
"Alex Smith"
""
"Richard Roe
Mary Major"