PowerShell脚本拆分CSV时双引号转义异常求助
解决PowerShell拆分CSV时双引号转义异常问题
你的问题出在直接按物理行读取CSV文件——CSV规范中,字段内的双引号会用两个双引号转义(如"字段内容包含""双引号""),甚至允许字段内存在换行。原脚本的ReadLine()会把这类逻辑行拆成多个物理行,导致后续写入时重复输出、内容错乱。
改用Microsoft.VisualBasic.FileIO.TextFieldParser来解析CSV,它能正确识别CSV的逻辑行(包括带转义引号、字段内换行的情况),修改后的Split-File函数如下:
param([string]$in_file, [string]$out_folder, [int]$linesperFile = 100000, [string]$ext = 'csv', [string]$header='Y', [string]$compress='Y') Function Split-File{ Param( $in_file, $out_folder, $linesperFile, $ext, $header ) # 加载TextFieldParser所需的程序集 Add-Type -AssemblyName Microsoft.VisualBasic $filecount = 1 $parser = $null $header_row = $null $writer = $null try{ # 初始化CSV解析器,指定分隔符为逗号,双引号为引号字符 $parser = New-Object Microsoft.VisualBasic.FileIO.TextFieldParser($in_file) $parser.TextFieldType = [Microsoft.VisualBasic.FileIO.FieldType]::Delimited $parser.SetDelimiters(',') $parser.HasFieldsEnclosedInQuotes = $true # 读取表头 if ($header -ne 'N') { $header_row = $parser.ReadFields() } # 创建第一个输出文件 $outputPath = Join-Path $out_folder "$($filecount.ToString("000")).$ext" $writer = [io.file]::CreateText($outputPath) $filecount++ $linecount = 0 # 写入表头(如果需要) if ($header -eq 'Y') { # 将表头数组转为CSV格式行(处理引号) $writer.WriteLine(($header_row | ForEach-Object { if ($_ -match '["",\r\n]') { "`"$($_.Replace('"', '""'))`"" } else { $_ } }) -join ',') } # 逐逻辑行读取并写入 while (!$parser.EndOfData) { try { $fields = $parser.ReadFields() # 将字段数组转为符合CSV规范的行 $csvLine = ($fields | ForEach-Object { if ($_ -match '["",\r\n]') { "`"$($_.Replace('"', '""'))`"" } else { $_ } }) -join ',' $writer.WriteLine($csvLine) $linecount++ # 达到行数限制时切换文件 if ($linecount -ge $linesperFile -and !$parser.EndOfData) { $writer.Dispose() $outputPath = Join-Path $out_folder "$($filecount.ToString("000")).$ext" $writer = [io.file]::CreateText($outputPath) $filecount++ $linecount = 0 # 新文件写入表头(如果需要) if ($header -eq 'Y') { $writer.WriteLine(($header_row | ForEach-Object { if ($_ -match '["",\r\n]') { "`"$($_.Replace('"', '""'))`"" } else { $_ } }) -join ',') } } } catch [Microsoft.VisualBasic.FileIO.MalformedLineException] { Write-Warning "跳过格式错误的行: $($_.Exception.Message)" } } } finally { # 清理资源 if ($writer) { $writer.Dispose() } if ($parser) { $parser.Close() } } return $filecount - 1 }
修改说明
- 使用TextFieldParser:专门处理CSV格式,自动识别带引号的字段、字段内换行,避免物理行拆分错误。
- 正确生成CSV行:写入时对包含引号、逗号或换行的字段重新添加双引号,并转义内部的双引号(替换为两个双引号),符合CSV规范。
- 错误处理:跳过格式错误的行,避免脚本中断。
内容的提问来源于stack exchange,提问作者PracticingPython
相关产品推荐
相关产品推荐

