Powershell 如何更快地过滤具有特定字符数的文件行?

Powershell 如何更快地过滤具有特定字符数的文件行?,powershell,powershell-4.0,Powershell,Powershell 4.0,所以我有一些顶起的平面文件,相当大 我尝试使用PowerShell只选择具有预期分隔符数量的行,并将它们输出到文件中 这项工作: function fixColDelim([string]$importFile) { $goodFile = $importFile.Replace(".txt", "_GOODX1.txt") $sr = New-Object -TypeName System.IO.StreamReader -ArgumentList $importFile $sw = New

所以我有一些顶起的平面文件,相当大

我尝试使用PowerShell只选择具有预期分隔符数量的行,并将它们输出到文件中

这项工作:

function fixColDelim([string]$importFile)
{
$goodFile = $importFile.Replace(".txt", "_GOODX1.txt")

$sr = New-Object -TypeName System.IO.StreamReader -ArgumentList $importFile
$sw = New-Object -TypeName System.IO.StreamWriter -ArgumentList $goodFile

$sr.ReadLine() | Out-Null
$sr.ReadLine() | Out-Null

While (-not $sr.EndOfStream) {
    $line = $sr.ReadLine().ToString()
    $gl = ($line.ToCharArray() | Where-Object {$_ -eq '|'} | Measure-Object).Count
    Write-Host $gl
    if($gl -eq 350)
    {
        $sw.WriteLine($sr.ReadLine())
    }
}
$sw.close()
$sr.close()
}
但是,它是RBAR,因此它不是针对500mb文件的最有效方法。有什么建议吗


Zach

您已经在使用streams了,它通常适用于更大的文件,在这种情况下也是一个不错的选择

在每个循环中,您将阅读两行。这会使您在文件中写入错误的行。改用为该行存储的变量

$sw.WriteLine($line)
下面这一行也是取得进展的好地方

这里有一些昂贵的操作。将行拆分为一个字符数组,
Measure Object
为大数组。我将进行测试,看看是否可以基准测试,但在这里使用一些正则表达式方法应该更快

$gl = ([regex]::Matches($line,"\|")).count
最后一件事,如果您对删除它感到满意的话,就是删除
Write Host
行。将数据写入控制台也是一个性能问题



您必须为此重构代码,我不知道这是否会更快,但您可以使用
-ReadCount
立即获取内容
一次提取大量文件

这里是替换正则表达式的替代方法

$gl = ($line -replace '[^|]','').length
如果您可能有嵌套的分隔符,那么您可以更进一步

$gl = ($line -replace '[^|"]','' -replace '"\|"',"").length

这么多代码来完成这么简单的事情。首先看一下
Select String
处理文件的速度:

Select-String $importfile -Pattern '([^|]+\|){350}' | Select line | Set-Content $goodfile
如果您想要更快的速度,请尝试将ReadCount传递给
Get Content
,它将成批流式处理您的文件。大概是这样的:

Get-Content $importfile -ReadCount 1000 | ? {$_ -match '([^|]+\|){350}'} | Set-Content $goodfile

你有什么版本的PowerShell?您是否假设它们不是文件中的嵌套分隔符?351列数据。。。damnI肯定有,但它不是文本限定的,所以很难找到它们。它是第4版。根据我的经验,
sls
不如
gc-readcount
或streamreaderymv快,
sls
在大多数情况下都是我的选择。是否可以读取到下一个crlf的位置(char(13)+char(10))。问题是文件不是文本限定的字段中的换行符不是嵌套的delims。因此,我可以删除该crlf,然后将其与后续行合并,并重新检查条数。如果一行分隔符之间包含空字段,则此正则表达式模式将不起作用(并且明显的替代方法
([^ |]*\\\\\\\\\\\\\\}{350}
将导致可怕的回溯)
Get-Content $importfile -ReadCount 1000 | ? {$_ -match '([^|]+\|){350}'} | Set-Content $goodfile