首页 > 解决方案 > 使用多行事件读取大型文本文件的最便宜和最快的方法

问题描述

我正在尝试读取具有多行事件的非常大的文本文件(~1.5-2GB),如下所示:

START--random stuff here 
more random stuff on this new line 
more stuff and things 
START--some random things 
additional random things 
blah blah 
START--data data more data 
START--things 
blah data

...但是以一种快速非资源密集型的方式。我不确定这种方法是否正确,但似乎仍然需要一段时间,而且我无法正确拆分事件,结果似乎是每一行。此外,每个步骤都需要很长时间才能完成,我想知道我是否可以一次完成每个步骤?

我正在建立这个例子

$NewContent = [System.IO.File]::ReadLines('E:\Scripts\Logs\First1000')
$global:results = $NewContent -split '(?m)^(?!\A)(?=START--)'

标签: .netpowershelltext

解决方案


带有选项的switch语句-File允许您逐行读取文件的行,从而使内存使用量保持较低且恒定;选项-Regex允许分支处理程序是正则表达式。

$eventLines = ''
switch -Regex -File 'E:\Scripts\Logs\First1000' {
  '^START--' { # Note that the regex is case-INsensitive
    if ($eventLines) { 
        # send previous events' lines to syslog
    }
    # Current line is the start of a new event.
    $eventLines = $_
  }
  default { 
    # Event-interior line, append it.
    $eventLines += [Envirionment]::NewLine + $_
  }
}
# Process last event.
if ($eventLines) { 
    # send last event's lines to syslog
}

System.IO.File.ReadLines()或者,您可以类似地修改您的解决方案并使用if带有字符串文字String.StartsWith()方法的语句,这比正则表达式匹配更快 - 但是,在我的非正式测试中,switch解决方案总体上似乎仍然更快。

$eventLines = ''
foreach ($line in [System.IO.File]::ReadLines('E:\Scripts\Logs\First1000')) {
  if ($line.StartsWith('START--')) {
    if ($eventLines) { 
        # send previous events' lines to syslog
    }
    # Current line is the start of a new event.
    $eventLines = $line
  } else {
    # Event-interior line, append it.
    $eventLines += [Environment]::NewLine + $line
  }
}
# Process last event.
if ($eventLines) { 
    # send last event's lines to syslog
}

推荐阅读