如何防止Import-Csv忽略空行?

问题描述 投票:0回答:2

背景

我有一个 CSV 文件,其中在单元格中包含空行和换行符,如下所示:


Richard Roe
Mary Major
"Alex Smith
Betty Brown
Chris Clark"

"Betty Brown
Donna Davis
Edward Evans"

Alex Smith

"Richard Roe
Mary Major"

Input CSV

我正在尝试编写一个 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"

Expected Result

问题

当您使用

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
忽略空行吗?

powershell csv import-csv
2个回答
0
投票

您实际上并不需要输入 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"

它与您想要的输出略有不同,但语义上是相同的。


0
投票

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"
© www.soinside.com 2019 - 2024. All rights reserved.