我正在处理一些数 GB 的文本文件,并希望使用 PowerShell 对它们进行一些流处理。这很简单,只需解析每一行并提取一些数据,然后将其存储在数据库中。
不幸的是,get-content | %{whatever($_)}
似乎将管道此阶段的整组行保留在内存中。它的速度也出奇的慢,需要很长时间才能真正读完。
所以我的问题分为两部分:
- 如何让它逐行处理流而不将整个内容缓冲在内存中?我希望避免为此使用几GB RAM。
- 如何让它运行得更快? PowerShell 迭代
get-content
似乎比 C# 脚本慢 100 倍。
我希望我在这里做了一些愚蠢的事情,比如缺少 -LineBufferSize
参数或其他东西......
最佳答案
如果您确实要处理数千兆字节的文本文件,请不要使用 PowerShell。即使您找到一种更快地读取它的方法,无论如何,在 PowerShell 中处理大量行都会很慢,并且您无法避免这种情况。即使是简单的循环也是昂贵的,例如对于 1000 万次迭代(在您的情况下相当真实),我们有:
# "empty" loop: takes 10 seconds
measure-command { for($i=0; $i -lt 10000000; ++$i) {} }
# "simple" job, just output: takes 20 seconds
measure-command { for($i=0; $i -lt 10000000; ++$i) { $i } }
# "more real job": 107 seconds
measure-command { for($i=0; $i -lt 10000000; ++$i) { $i.ToString() -match '1' } }
更新:如果您仍然不害怕,那么尝试使用 .NET 阅读器:
$reader = [System.IO.File]::OpenText("my.log")
try {
for() {
$line = $reader.ReadLine()
if ($line -eq $null) { break }
# process the line
$line
}
}
finally {
$reader.Close()
}
更新2
有关于可能更好/更短的代码的评论。 for
的原始代码没有任何问题,也不是伪代码。但阅读循环的较短(最短?)变体是
$reader = [System.IO.File]::OpenText("my.log")
while($null -ne ($line = $reader.ReadLine())) {
$line
}
关于powershell - 如何在 PowerShell 中将文件作为流逐行处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4192072/