我正在尝试编写PowerShell脚本来对生产日志文件进行一些分析。
我需要按大约50到100个值过滤大约250万行文本 - 如果O(nm)
,则需要250,000,000次迭代。
我已经尝试Get-Content | Select-String
,但这似乎非常缓慢。
是否有任何方法来处理此问题,而不是为每个值迭代每一行一次?
因此,日志文件看起来有点像这样(datetime:process_id:log_level:message)
2016-01-30 14:01:22.349 [ 27] INFO XXX YYY XXXFX
2016-01-30 14:01:28.146 [ 16] INFO XXXD YY Z YYY XXXX
2016-01-30 14:01:28.162 [ 16] DEBUG YY XXXXX YY XX P YYY
2016-01-30 14:01:28.165 [ 16] DEBUG YY XXXXX YY XX YYY
2016-01-30 14:01:28.167 [ 16] DEBUG YY XXXXX YY XX YYY
2016-01-30 14:01:28.912 [ 27] INFO XXX YY XXGXXX YYYYYY YY XX
我可能正在寻找值D,F,G和Z。
值可以是二进制数字的字符串,十六进制数字,两者的组合,常规文本和标点符号的字符串,或管道分隔的值。
答案 0 :(得分:4)
经验法则:
StreamReader
的速度比Get-Content
快于Import-Csv
。如果它足以检查你的日志行是否包含任何给定的字符串,你可能想要这样的东西:
$reader = [IO.StreamReader]'C:\path\to\your.log'
$filters = 'foo', 'bar', ...
while ($reader.Peek() -ge 0) {
$line = $reader.ReadLine()
if ($filters | Where-Object {$line.Contains($_)}) {
$line
}
}
$reader.Close()
$reader.Dispose()
如果您想使用StreamWriter
而不是仅仅回显输出,只需调整代码如下:
$reader = [IO.StreamReader]'C:\path\to\your.log'
$writer = [IO.StreamWriter]'C:\path\to\output.txt'
$filters = 'foo', 'bar', ...
while ($reader.Peek() -ge 0) {
$line = $reader.ReadLine()
if ($filters | Where-Object {$line.Contains($_)}) {
$writer.WriteLine($line)
}
}
$reader.Close(); $reader.Dispose()
$writer.Close(); $writer.Dispose()
根据日志行的结构以及过滤器值以及如何应用它们,过滤器逻辑可能需要进行调整。但是,您需要实际显示日志格式并过滤示例。
答案 1 :(得分:3)
我会尝试使用StreamReader
+ StreamWriter
来加快读/写速度,因为Get-Content
对于大文件来说速度很慢。此外,我会尝试制作一个正则表达式(word OR word OR word
等),以避免数百次迭代。例如:
$words = "foo","bar","donkey"
#Create regex-pattern (usually faster to match)
$regex = ($words | % { [regex]::Escape($_) }) -join '|'
$reader = New-Object System.IO.StreamReader -ArgumentList "c:\myinputfile.txt"
$writer = New-Object System.IO.StreamWriter -ArgumentList "c:\myOUTputfile.txt"
while (($line = $reader.ReadLine()) -ne $null) {
if($line -match $regex) { $writer.WriteLine($line) }
}
#Close writer
$writer.Close()
$writer.Dispose()
#Close reader
$reader.Close()
$reader.Dispose()