【发布时间】:2020-06-22 15:25:51
【问题描述】:
在 PowerShell 脚本中,我读取了一个 CSV 文件。
我必须“修复”一些价值观。具体来说,CSV 可能包含一个空值,即字面意义上的NULL 或有时-。所有这些值都将被视为$null。
有没有办法拦截 CSV 解析来处理它?
实际上我有一个可行的解决方案,但该解决方案非常缓慢。迭代 2500 多个项目需要 20 分钟,而按原样读取 CSV 文件只需几秒钟。
这个想法是迭代每个属性:
$private:result = @{}
foreach($private:prop in $private:line.PSObject.Properties){
$private:value = $null
$private:result.Add($private:prop.Name, ($private:value | Filter-Value))
}
$private:result
...
function Filter-Value{
param(
[Parameter(Position=0, ValueFromPipeline=$true)]
[object]$In
)
if(-not $In){
$null
}
elseif(($In -is [string]) -and ($In.Length -eq 0)) {
$null
}
elseif(($In -eq "NULL") -or ($In -eq "-")) {
$null
}
else{
$In
}
}
完整代码:
function Import-CsvEx{
param(
[Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
[ValidateScript({Test-Path $_ -PathType Leaf})]
[string]$Path,
[Parameter()]
[string]$Delimiter
)
begin{
Write-Verbose "Begin read of file $Path"
}
process{
# We use file stream and stream reader to automatically detect encoding
$private:fileStream = [System.IO.File]::OpenRead($Path)
$private:streamReader = New-Object System.IO.StreamReader($private:fileStream, [System.Text.Encoding]::Default, $true)
$private:fileContent = $private:streamReader.ReadToEnd()
$private:streamReader.Dispose()
$private:fileStream.Dispose()
$private:csv = ConvertFrom-Csv $private:fileContent -Delimiter $Delimiter
for($private:i=0; $private:i -lt $private:csv.Count ; $private:i++){
Write-Progress -Id 1003 -Activity "Reading CSV" -PercentComplete ($private:i*100/$private:csv.count)
$private:line = $private:csv[$private:i]
$private:result = @{}
foreach($private:prop in $private:line.PSObject.Properties){
$private:value = $null
$private:result.Add($private:prop.Name, ($private:value | Filter-Value))
}
# actually outputs the object to the pipeline
New-Object psobject -Property $private:result
}
Write-Progress -Id 1003 -Activity "Reading CSV" -Completed
}
end{
Write-Verbose "End read of file $Path"
}
}
function Filter-Value{
param(
[Parameter(Position=0, ValueFromPipeline=$true)]
[object]$In
)
if(-not $In){
$null
}
elseif(($In -is [string]) -and ($In.Length -eq 0)) {
$null
}
elseif(($In -eq "NULL") -or ($In -eq "-")) {
$null
}
else{
$In
}
}
【问题讨论】:
标签: performance powershell csv