从CSV文件的字符串列中删除换行符

7
我有一个CSV文件,其中一个字符串列跨越多行。我想将这些多行聚合成一行。
例如:
1, "asdsdsdsds", "John"
2, "dfdhifdkinf
dfjdfgkdnjgknkdjgndkng
dkfdkjfnjdnf", "Roy"
3, "dfjfdkgjfgn", "Rahul"

我希望我的输出是。
1, "asdsdsdsds", "John"
2, "dfdhifdkinf dfjdfgkdnjgknkdjgndkng dkfdkjfnjdnf", "Roy"
3, "dfjfdkgjfgn", "Rahul"

我希望能够使用PowerShell实现这个输出。

谢谢。


第二行第二列缺少的双引号是故意的还是打错了?这些字符串中可能包含逗号吗? - Ansgar Wiechers
打字错误...抱歉。 已经更正了! - Varun Gupta
在PHP中该如何实现? - Vishal Kumar Sahu
5个回答

5

在Ansgar的回答基础上,以下是当你需要这么做时的操作步骤:

  • You don't know the column names
  • Your CSV file may contain CR or LF independently

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

4

试试这个:

$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

谢谢Ansgar! 有一个小问题,是否有办法从CSV输出中删除标题? - Varun Gupta
当我尝试在Excel中打开新创建的CSV文件时,它只会在一列中打开。如何解决这个问题? - Varun Gupta
那将是一个新问题,而且还是一个针对超级用户的问题。这个问题可能与文件扩展名有关,你选择了哪个分隔符以及如何在Excel中打开文件。 - Ansgar Wiechers
我不确定,但是上述命令似乎无法从CSV文件的某一列中删除换行符。 - Varun Gupta
也许只是一个单独的LF字符,而不是Windows默认的CR-LF?尝试使用-replace“`r”-replace“`n”,' '代替-replace“`r`n”,' ' - Ansgar Wiechers
显示剩余2条评论

2
你可以导入CSV文件,进行专门的选择操作,并将结果写入新的CSV文件。
import-csv Before.csv -Header "ID","Change" | Select ID,@{Name="NoNewLines", Expression={$_.Change -replace "`n"," "}} | export-csv After.csv

关键部分在于选择语句,它允许您传递一个专门的哈希表(Name是属性的名称,Expression是计算属性值的脚本块)。
您可能需要微调标题以获得所需的精确输出。

哈希表作为属性定义技术现已在概念性about_Calculated_Properties帮助主题中得到了适当的记录。如果要替换CRLF和LF换行符,请使用'\r?\n'而不是"`n" - mklement0

0

Export-CSV存在两个问题:

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

解决上述两个问题的方法是改用Convertto-CSV。以下是一个示例:

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

请注意,这使您可以对数据进行任何编辑(在本例中替换换行数据),并使用重定向符号进行追加。

0

提示:我已经创建了一个 CSV 清理工具: 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 ':' 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接