【问题标题】:Powershell Parsing Pipeline CSV data with newlines using ConvertFrom-CsvPowershell 使用 ConvertFrom-Csv 使用换行符解析管道 CSV 数据
【发布时间】:2018-11-09 01:10:21
【问题描述】:

当尝试在字段内使用换行符解析 CSV 数据时,ConvertFrom-Csv 将无法正常工作。这是一个例子:


test.csv

name,address
John Doe,"123 Easy Way
Apt. 10
Somewhere, USA"
Jane Doe,"456 Main St
Unit 5
SomewhereElse, USA"

正确解析

> Import-Csv test.csv

name     address
----     -------
John Doe 123 Easy Way...
Jane Doe 456 Main St...

解析不当

> Get-Content test.csv | ConvertFrom-Csv

name          address
----          -------
John Doe      123 Easy Way
Apt. 10
Somewhere     USA"
Jane Doe      456 Main St
Unit 5
SomewhereElse USA"

如此处所示,换行符被解析为新记录,而不是字段中的换行符。你如何解决这个问题?

【问题讨论】:

标签: powershell csv


【解决方案1】:

当尝试在字段内使用换行符解析 CSV 数据时,会出现使用 ConvertFrom-Csv 方法的问题。这是因为换行符被用作分隔符,而不是传递给 ConvertFromCsv 方法。 根据您获取 CSV 的方式,解决此问题的方法会有所不同:

使用-Raw 开关正确解析

PS> Get-Content -raw test.csv | ConvertFrom-Csv

name     address
----     -------
John Doe 123 Easy Way...
Jane Doe 456 Main St...

虽然这适用于 Get-Content 命令,但不适用于可能将 CSV 返回到管道的任意命令。要处理这些情况,请通过“Out-String”命令管道输出。

正确的管道解析

我发现有 2 个变体可以使用:

PS> <command> | Out-String | ConvertFrom-Csv

以下方法归功于#Powershell 中的 sifb。它有点“hacky”,但工作得很好并且可以有它的用途。

PS> (<command>) -join "`r`n" | ConvertFrom-Csv

【讨论】:

    【解决方案2】:

    这是相当脆弱的,因为它对每条记录的行数进行了硬编码。但是,它适用于您的示例数据集。 [grin] 我怀疑精心编写的正则表达式会更快地完成这项工作,但我无法想出这样的方法。

    # fake reading in a text file
    #    in real life, use "Get-Content"
    $InStuff = @'
    name,address
    John Doe,"123 Easy Way
    Apt. 10
    Somewhere, USA"
    Jane Doe,"456 Main St
    Unit 5
    SomewhereElse, USA"
    '@ -split [environment]::NewLine
    
    $CleanedInStuff = foreach ($Index in 0..$InStuff.GetUpperBound(0))
        {
        if ($Index -eq 0)
            {
            $InStuff[$Index]
            continue
            }
        if (-not [string]::IsNullOrEmpty($InStuff[$Index]))
            {
            ($InStuff[$Index..($Index + 2)]) -join ', '
    
            $InStuff[$Index + 1] = ''
            $InStuff[$Index + 2] = ''
            }
        }
    
    $FromCSV = $CleanedInStuff |
        ConvertFrom-Csv
    
    $FromCSV |
        Export-Csv -LiteralPath "$env:TEMP\Hobadee.csv" -NoTypeInformation
    
    '=' * 40
    $CleanedInStuff
    '=' * 40
    $FromCSV
    

    屏幕输出...

    ========================================
    name,address
    John Doe,"123 Easy Way, Apt. 10, Somewhere, USA"
    Jane Doe,"456 Main St, Unit 5, SomewhereElse, USA"
    ========================================
    
    name     address                                
    ----     -------                                
    John Doe 123 Easy Way, Apt. 10, Somewhere, USA  
    Jane Doe 456 Main St, Unit 5, SomewhereElse, USA
    

    CSV 文件内容...

    "name","address"
    "John Doe","123 Easy Way, Apt. 10, Somewhere, USA"
    "Jane Doe","456 Main St, Unit 5, SomewhereElse, USA"
    

    【讨论】:

      猜你喜欢
      • 2021-12-19
      • 2015-08-09
      • 2014-11-18
      • 2017-10-14
      • 2012-09-16
      • 2013-08-24
      • 2018-03-18
      • 1970-01-01
      • 2019-09-12
      相关资源
      最近更新 更多