如何避免PowerShell中Import-Csv忽略空行?
问题:如何阻止PowerShell的
Import-Csv忽略CSV文件中的空行? 背景
我有一个包含空行和单元格内换行的CSV文件,内容如下:
Richard Roe Mary Major "Alex Smith Betty Brown Chris Clark" "Betty Brown Donna Davis Edward Evans" Alex Smith "Richard Roe Mary Major"
我需要编写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"
遇到的问题
使用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读取文件,但处理单元格内的换行逻辑会变得非常复杂。
核心疑问
是否有办法阻止Import-Csv忽略CSV文件中的空行?
补充信息
另有一个存储部门-名称映射关系的CSV文件,内容如下:
Legal,Richard Roe Accounting,Mary Major R&D,Alex Smith R&D,Betty Brown Design,Chris Clark Design,Donna Davis Design,Edward Evans
解决方案
Import-Csv本身没有内置参数保留空行(因为CSV规范中空行通常被视为无效行),但可以通过以下两种方法实现需求:
方法1:预处理文件,标记空行后再导入
先读取文件内容,将空行替换为表示空单元格的"",导入后再还原为空行:
# 读取原始文件,将空行替换为""(空CSV单元格) $processedContent = Get-Content .\NamesList.csv -Raw -Encoding UTF8 | ForEach-Object { $_ -replace '^\s*$', '""' } # 将处理后的内容转为CSV对象 $csvData = $processedContent | ConvertFrom-Csv -Header Names # 遍历结果,把标记的空单元格还原为空行对应的空对象 $csvData | ForEach-Object { if ([string]::IsNullOrEmpty($_.Names)) { [PSCustomObject]@{ Names = $null } } else { $_ } }
方法2:使用.NET TextFieldParser解析(推荐)
借助.NET的TextFieldParser组件,它可以正确识别带换行的单元格,同时保留空行:
# 加载必要的程序集 Add-Type -AssemblyName Microsoft.VisualBasic # 初始化解析器 $parser = New-Object Microsoft.VisualBasic.FileIO.TextFieldParser -ArgumentList ".\NamesList.csv" $parser.SetDelimiters(',') $parser.HasFieldsEnclosedInQuotes = $true # 启用引号包裹字段的解析 $parsedResults = @() while (-not $parser.EndOfData) { try { $fields = $parser.ReadFields() if ($fields -eq $null) { # 处理空行,添加空对象 $parsedResults += [PSCustomObject]@{ Names = $null } } else { # 读取正常行的内容 $parsedResults += [PSCustomObject]@{ Names = $fields[0] } } } catch { # 处理异常行,这里同样视为空行 $parsedResults += [PSCustomObject]@{ Names = $null } } } $parser.Close() # 输出包含空行的结果 $parsedResults
后续:插入部门名称
得到保留空行的CSV数据后,结合部门映射文件完成部门插入逻辑:
# 导入部门映射表 $departmentMap = Import-Csv .\DeptMap.csv -Header Department, Name # 处理每个条目生成目标格式 $parsedResults | ForEach-Object { if (-not [string]::IsNullOrEmpty($_.Names)) { $nameList = $_.Names -split "`n" | ForEach-Object { $_.Trim() } $outputLines = @() foreach ($name in $nameList) { $dept = $departmentMap | Where-Object { $_.Name -eq $name } | Select-Object -ExpandProperty Department $outputLines += "$dept`n$name" } # 用引号包裹结果 '"' + ($outputLines -join "`n") + '"' } else { # 空行直接输出空行 "" } }
内容的提问来源于stack exchange,提问作者SATO Yusuke
相关产品推荐
相关产品推荐

