首页 > 解决方案 > 如何检查/强制执行下一个 cmdlet 以获取管道对象

问题描述

我对如何在 Powershell 中对 3000 万条 csv 记录进行排序这个问题很感兴趣,并提出了一个构建临时文件的解决方案。现在我正在尝试提出另一种方法,它首先构建一个排序的索引列表([int[]]),然后从源文件中选择大部分索引(例如1e6)并将它们放到管道中:

Function Sort-BigCsv {
    [CmdletBinding()] param(
        [string]$FilePath,
        [String]$Property,
        [Int]$BulkSize = 1e6,
        [System.Text.Encoding]$Encoding = [System.Text.Encoding]::Default
    )
    Begin {
        if ($FilePath.StartsWith('.\')) { $FilePath = Join-Path (Get-Location) $FilePath }
        $Index = 0
        $Dictionary = [System.Collections.Generic.SortedDictionary[string, int]]::new()
        Import-Csv $FilePath -Encoding $Encoding | Foreach-Object { $Dictionary[$_.$Property] = $Index++ }
        $IndexList = [int[]]($Dictionary.Values)
        $Dictionary = $Null                                     # we only need the sorted index list
    }
    Process {
        $Start = 0
        While ($Start -lt $IndexList.Count) {
            [System.GC]::Collect()
            $End = $Start + $BulkSize - 1
            if ($End -ge $IndexList.Count) { $End = $IndexList.Count - 1 }
            Import-Csv $FilePath -Encoding $Encoding |
                Select-Object -Index $IndexList[$Start..$End] | # Note that the -Index parameter reorders the list
                    Sort-Object $Property |                     # Consider smarter sort as this has already be done before
            $Start = $End + 1
        }
    }
}

例子:

Sort-BigCsv .\Input.Csv Id -BulkSize 100 # | Export-Csv .\Output.Csv

我认为这背后的一般想法应该可行,但我第二次猜测 PowerShell 在将对象传递给下一个 cmdlet(/display) 方面实际上在做什么,并且出现的问题如下:

也许它只是按预期工作(很难从任务管理器中的内存大小中分辨出来),但我想确认这一点......是否有任何检查和/或控制是否传递项目(或写输出之后总是这样吗?意思是,如果最后一个 cmdlet 停止,第一个 cmdlet 也需要停止...)

标签: performancepowershellmemorypipeline

解决方案


推荐阅读