regex - 有没有一种方法可以优化我的 Powershell 函数以从大文件中删除模式匹配?

标签 regex powershell optimization powershell-4.0

我有一个很大的文本文件(约 2 万行,每行约 80 个字符)。 我还有一个较大的对象数组(约 1500 项),其中包含我希望从大型文本文件中删除的模式。请注意,如果数组中的模式出现在输入文件的一行中,我希望删除整行,而不仅仅是模式。

输入文件是 CSVish,包含类似以下行:

A;AAA-BBB;XXX;XX000029;WORD;WORD-WORD-1;00001;STRING;2015-07-01;;010;   

我在输入文件的每一行中搜索的数组中的模式类似于

XX000029

上面一行的一部分。

我实现这个目标的有点幼稚的功能目前看起来像这样:

function Remove-IdsFromFile {
  param(
    [Parameter(Mandatory=$true,Position=0)]
    [string]$BigFile,
    [Parameter(Mandatory=$true,Position=1)]
    [Object[]]$IgnorePatterns
  )

  try{
    $FileContent = Get-Content $BigFile
  }catch{
    Write-Error $_
  }

  $IgnorePatterns | ForEach-Object {
    $IgnoreId = $_.IgnoreId
    $FileContent = $FileContent | Where-Object { $_ -notmatch $IgnoreId }
    Write-Host $FileContent.count
  }
  $FileContent | Set-Content "CleansedBigFile.txt"
}

这有效,但是

我怎样才能让它更快?

最佳答案

function Remove-IdsFromFile {
    param(
        [Parameter(Mandatory=$true,Position=0)]
        [string]$BigFile,
        [Parameter(Mandatory=$true,Position=1)]
        [Object[]]$IgnorePatterns
    )

    # Create the pattern matches
    $regex = ($IgnorePatterns | ForEach-Object{[regex]::Escape($_)}) -join "|"

    If(Test-Path $BigFile){
    $reader = New-Object  System.IO.StreamReader($BigFile)

    $line=$reader.ReadLine()
    while ($line -ne $null)
    {
        # Check if the line should be output to file
        If($line -notmatch $regex){$line | Add-Content "CleansedBigFile.txt"}

        # Attempt to read the next line. 
        $line=$reader.ReadLine()
    }

    $reader.close()

    } Else {
        Write-Error "Cannot locate: $BigFile"
    }
}

StreamReader 是读取大型文本文件的首选方法之一。我们还使用正则表达式来构建模式字符串以进行匹配。对于模式字符串,如果存在正则表达式控制字符,我们使用 [regex]::Escape() 作为预防措施。必须猜测,因为我们只看到一个模式字符串。

如果 $IgnorePatterns 可以很容易地转换为字符串,这应该可以正常工作。 $regex 的一小部分示例如下:

XX000029|XX000028|XX000027

如果 $IgnorePatterns 是从数据库中填充的,您可能对此控制较少,但由于我们使用的是正则表达式,您可能能够通过实际使用减少该模式集正则表达式(而不仅仅是一个大的替代匹配)就像我上面的例子一样。例如,您可以将其减少到 XX00002[7-9]

我不知道正则表达式本身是否会提供 1500 种可能的性能提升。 StreamReader 应该是这里的焦点。然而,我确实通过对输出使用 Add-Content 来玷污水域,这也没有因为速度快而获得任何奖励(可以在其位置使用流编写器)。

读者和作家

我仍然需要对其进行测试以确保其正常工作,但这仅使用了 streamreaderstreamwriter。如果它确实工作得更好,我将替换上面的代码。

function Remove-IdsFromFile {
    param(
        [Parameter(Mandatory=$true,Position=0)]
        [string]$BigFile,
        [Parameter(Mandatory=$true,Position=1)]
        [Object[]]$IgnorePatterns
    )

    # Create the pattern matches
    $regex = ($IgnorePatterns | ForEach-Object{[regex]::Escape($_)}) -join "|"

    If(Test-Path $BigFile){
        # Prepare the StreamReader
        $reader = New-Object System.IO.StreamReader($BigFile)

        #Prepare the StreamWriter
        $writer = New-Object System.IO.StreamWriter("CleansedBigFile.txt")

        $line=$reader.ReadLine()
        while ($line -ne $null)
        {
            # Check if the line should be output to file
            If($line -notmatch $regex){$writer.WriteLine($line)}

            # Attempt to read the next line. 
            $line=$reader.ReadLine()
        }

        # Don't cross the streams!
        $reader.Close()
        $writer.Close()

    } Else {
        Write-Error "Cannot locate: $BigFile"
    }
}

对于流,您可能需要在其中进行一些错误预防,但它确实可以正常工作。

关于regex - 有没有一种方法可以优化我的 Powershell 函数以从大文件中删除模式匹配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31674667/

相关文章:

regex - 在 awk 中使用匹配模式

c# - 'generic' 电话号码的基本正则表达式

javascript - 解析 YouTube URL

azure - 设置-AzKeyVaultAccessPolicy : Cannot find the Active Directory object '' in tenant

c# - 复制文件夹并保留权限

powershell - 如何在 PowerShell 7 中使用 AzureRm 模块?

apache-flex - 优化 Flex 应用程序 - 在哪里可以找到我的瓶颈

php - 使用正则表达式获取标签内的引​​号

javascript - 优化 JavaScript 加载的最佳实践

Java方法优化