[powershell] PowerShell에서 파일을 한 줄씩 스트림으로 처리하는 방법

몇 기가 바이트 텍스트 파일로 작업 중이며 PowerShell을 사용하여 스트림 처리를 수행하고 싶습니다. 각 줄을 구문 분석하고 일부 데이터를 추출한 다음 데이터베이스에 저장하는 간단한 작업입니다.

불행히도 get-content | %{ whatever($_) }파이프의이 단계에서 전체 라인 세트를 메모리에 유지하는 것으로 보입니다. 또한 놀랍도록 느려 실제로 모든 것을 읽는 데 매우 오랜 시간이 걸립니다.

그래서 제 질문은 두 부분입니다.

  1. 전체를 메모리에 버퍼링하지 않고 줄 단위로 스트림을 처리하려면 어떻게해야합니까? 이 목적을 위해 몇 기가의 RAM을 사용하는 것을 피하고 싶습니다.
  2. 더 빨리 실행하려면 어떻게해야합니까? 을 반복하는 PowerShell get-content은 C # 스크립트보다 100 배 느립니다.

-LineBufferSize매개 변수를 놓친 것 같은 멍청한 일이 있기를 바랍니다 .



답변

실제로 수 기가 바이트 텍스트 파일로 작업하려는 경우 PowerShell을 사용하지 마십시오. 읽는 방법을 찾더라도 엄청난 양의 줄을 더 빠르게 처리하는 것은 어쨌든 PowerShell에서 느리며 이것을 피할 수 없습니다. 단순한 루프조차도 비용이 많이 듭니다. 예를 들어 1,000 만 번의 반복 (귀하의 경우에는 실제)에 대해 다음과 같이합니다.

# "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
}


답변

System.IO.File.ReadLines()이 시나리오에 완벽합니다. 파일의 모든 줄을 반환하지만 줄을 즉시 반복 할 수 있으므로 전체 내용을 메모리에 저장할 필요가 없습니다.

.NET 4.0 이상이 필요합니다.

foreach ($line in [System.IO.File]::ReadLines($filename)) {
    # do something with $line
}

http://msdn.microsoft.com/en-us/library/dd383503.aspx


답변

직접 PowerShell을 사용하려면 아래 코드를 확인하십시오.

$content = Get-Content C:\Users\You\Documents\test.txt
foreach ($line in $content)
{
    Write-Host $line
}


답변