【问题标题】:Remove New Line Character from CSV file's string column从 CSV 文件的字符串列中删除换行符
【发布时间】:2013-09-08 07:41:37
【问题描述】:

我有一个带有字符串列的 CSV 文件,该列跨越多行。我想将这些多行聚合为一行。

例如

1, "asdsdsdsds", "John"
2, "dfdhifdkinf
dfjdfgkdnjgknkdjgndkng
dkfdkjfnjdnf", "Roy"
3, "dfjfdkgjfgn", "Rahul"

我希望我的输出是

1, "asdsdsdsds", "John"
2, "dfdhifdkinf dfjdfgkdnjgknkdjgndkng dkfdkjfnjdnf", "Roy"
3, "dfjfdkgjfgn", "Rahul"

我想使用 PowerShell 实现这个输出

谢谢。

【问题讨论】:

  • 第 2 行第 2 列末尾缺少的双引号是故意的还是错字?字符串可以包含逗号吗?
  • 错字...对不起。更正了!
  • 用 PHP 怎么做?

标签: powershell csv


【解决方案1】:

您可以导入 csv,进行专门的选择,然后将结果写入新的 CSV。

import-csv Before.csv -Header "ID","Change" | Select ID,@{Name="NoNewLines", Expression={$_.Change -replace "`n"," "}} | export-csv After.csv

关键部分在 select 语句中,它允许您传递专门的哈希表(Name 是属性的名称,Expression 是计算它的脚本块)。

您可能需要稍微调整一下标题才能获得所需的确切输出。

【讨论】:

    【解决方案2】:

    试试这个:

    $csv = 'C:\path\to\your.csv'
    
    (Import-Csv $csv -Header 'ID','Value','Name') | % {
      $_.Value = $_.Value -replace "`r`n",' '
      $_
    } | Export-Csv $csv -NoTypeInformation
    

    如果您的 CSV 包含标题,请从导入中删除 -Header 'ID','Value','Name' 并将 Value 替换为实际的列名。

    如果您不想在字段中加上双引号,可以通过将 Export-Csv 替换为以下内容来删除它们:

    ... | ConvertTo-Csv -NoTypeInformation | % { $_ -replace '"' } | Out-File $csv
    

    要从输出中删除标题,请在 Out-File 之前添加另一个过滤器以跳过第一行:

    ... | select -Skip 1 | Out-File $csv
    

    【讨论】:

    • 除了上面的问题,我在每一列都有双引号。在同一个脚本中,如何将双引号替换为空白字符?
    • 谢谢安斯加尔!!一个小问题,有没有办法从 CSV 输出中删除标题?
    • 当我尝试在 excel 中打开新创建的 csv 文件时,它只在一列中打开。怎么解决?
    • 这将是一个新问题,并且是 SuperUser 的一个问题。问题可能与文件的扩展名、您选择的分隔符以及在 Excel 中打开文件的方式有关。
    • 我不确定,但上述命令无法从 csv 文件的一列中删除换行符。
    【解决方案3】:

    基于 Ansgar 的回答,以下是在以下情况下的操作方法:

    • 您不知道列名
    • 您的 CSV 文件可能单独包含 CR 或 LF

      (Import-Csv $csvInput) | % {
          $line = $_
          foreach ($prop in $line.PSObject.Properties) {
              $line.($prop.Name) = ($prop.Value -replace '[\r\n]',' ')
          }
          $line
      } | Export-Csv $csvOutput -NoTypeInformation
      

    【讨论】:

      【解决方案4】:

      Export-CSV 的问题是双重的:

      • 早期版本(powershell1 和 2)不允许您将数据附加到 CSV
      • 如果传送给它的数据包含换行符,则该数据在 Excel 中无用

      解决上述两种情况的方法是改用 Convertto-CSV。这是一个示例:

      {bunch of stuff} | ConvertTo-CSV | %{$_ -replace "`n","<NL>"} | %{$_ -replace "`r","<CR>"} >>$AppendFile
      

      请注意,这允许您对数据进行任何编辑(在这种情况下,替换换行数据),并使用重定向器追加。

      【讨论】:

        【解决方案5】:

        仅供参考:我创建了一个 CSV Cleaner:https://stackoverflow.com/a/32016543/361842

        这可用于替换任何不需要的字符/应该直接适应您的需求。

        下面复制的代码;虽然我建议参考上述线程以查看其他人的任何反馈。

        clear-host
        [Reflection.Assembly]::LoadWithPartialName("System.IO") | out-null
        [Reflection.Assembly]::LoadWithPartialName("Microsoft.VisualBasic") | out-null
        
        function Clean-CsvStream {
            [CmdletBinding()]
            param (
                [Parameter(Mandatory = $true, ValueFromPipeline=$true)]
                [string]$CsvRow
                ,
                [Parameter(Mandatory = $false)]
                [char]$Delimiter = ','
                ,
                [Parameter(Mandatory = $false)]
                [regex]$InvalidCharRegex 
                ,
                [Parameter(Mandatory = $false)]
                [string]$ReplacementString 
        
            )
            begin {
                [bool]$IsSimple = [string]::IsNullOrEmpty($InvalidCharRegex) 
                if(-not $IsSimple) {
                    [System.IO.MemoryStream]$memStream = New-Object System.IO.MemoryStream
                    [System.IO.StreamWriter]$writeStream = New-Object System.IO.StreamWriter($memStream)
                    [Microsoft.VisualBasic.FileIO.TextFieldParser]$Parser = new-object Microsoft.VisualBasic.FileIO.TextFieldParser($memStream)
                    $Parser.SetDelimiters($Delimiter)
                    $Parser.HasFieldsEnclosedInQuotes = $true
                    [long]$seekStart = 0
                }
            }
            process {
                if ($IsSimple) {
                    $CsvRow
                } else { #if we're not replacing anything, keep it simple
                    $seekStart = $memStream.Seek($seekStart, [System.IO.SeekOrigin]::Current) 
                    $writeStream.WriteLine($CsvRow)
                    $writeStream.Flush()
                    $seekStart = $memStream.Seek($seekStart, [System.IO.SeekOrigin]::Begin) 
                    write-output (($Parser.ReadFields() | %{$_ -replace $InvalidCharRegex,$ReplacementString }) -join $Delimiter)
                }
            }
            end {
                if(-not $IsSimple) {
                    try {$Parser.Close(); $Parser.Dispose()} catch{} 
                    try {$writeStream.Close(); $writeStream.Dispose()} catch{} 
                    try {$memStream.Close(); $memStream.Dispose()} catch{} 
                }
            }
        }
        $csv = @(
            (new-object -TypeName PSCustomObject -Property @{A="this is regular text";B="nothing to see here";C="all should be good"}) 
            ,(new-object -TypeName PSCustomObject -Property @{A="this is regular text2";B="what the`nLine break!";C="all should be good2"}) 
            ,(new-object -TypeName PSCustomObject -Property @{A="this is regular text3";B="ooh`r`nwindows line break!";C="all should be good3"}) 
            ,(new-object -TypeName PSCustomObject -Property @{A="this is regular text4";B="I've got;a semi";C="all should be good4"}) 
            ,(new-object -TypeName PSCustomObject -Property @{A="this is regular text5";B="""You're Joking!"" said the Developer`r`n""No honestly; it's all about the secret VB library"" responded the Google search result";C="all should be good5"})
        ) | convertto-csv -Delimiter ';' -NoTypeInformation
        $csv | Clean-CsvStream -Delimiter ';' -InvalidCharRegex "[`r`n;]" -ReplacementString ':' 
        

        【讨论】:

          猜你喜欢
          • 2020-05-27
          • 2018-07-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-10-25
          • 2011-10-13
          相关资源
          最近更新 更多