从大型文本文件导出行范围

Exporting ranges of rows from large text files

我有大约 5GB 的日志数据,我需要过滤并找到匹配的行,然后包括来自匹配行的 +/- 75 行。如果数据的格式很重要,它会损坏 XML,缺少一些标签。

我查找匹配行的代码:

$ExampleFile = [System.IO.File]::ReadLines("C:\temp\filestomove\ExampleLog.txt") 
$AccountNumber = "*123456789*"
$LineCount = 0
$RowsToExport = @()
foreach($line in $ExampleFile){

  if($line -like "*$AccountNumber*"){
    $RowsToExport += $LineCount
  }
  $LineCount += 1 
}

以上代码相当快速地完成了这项工作,它每秒管理大约 1 MB 的日志。这是我可以接受的速度,因为它是一次性工作。

我正在努力解决的问题是以不太慢的方式导出匹配的行。

我当前的代码如下所示:

foreach($row in $RowsToExport){
$IndexRangeHigh = [int]$row + 75
$IndexRangeLow = [int]$row - 75

$test | select -Index ($IndexRangeLow..$IndexRangeHigh) | out-file C:\temp\Example.txt -append 
}

这需要很长时间,我对使用 select -index 表示怀疑,因为我怀疑它很慢。

上面的测量命令在 50MB 的测试文件上给出了以下结果:

TotalDays         : 0,00354806909375
TotalHours        : 0,08515365825
TotalMinutes      : 5,109219495
TotalSeconds      : 306,5531697
TotalMilliseconds : 306553,1697

读取文件和匹配行只花了我 55 秒。

总结一个问题:

如何从一个大变量中导出一系列行?我可以使用其他方法从 $ExampleFile 变量中 select 行而不是使用 select -index ($ExampleRangeLow..$ExampleRangeHigh)?

PowerShell 有一个 cmdlet (Select-String),允许在匹配后 and/or 之前提取文本。

Select-String -Path 'C:\path\to\your.log' -Pattern '123456789' -Context 75

Select-String 的输出是一个具有多个属性的对象,因此如果您需要文本形式的匹配行,则需要额外的代码:

... | ForEach-Object {
  $pre  = $_.Context.PreContext | Out-String
  $post = $_.Context.PostContext | Out-String

  "{0}{1}`n{2}" -f $pre, $_.Line, $post
}