PowerShell에서 한 줄씩 파일 읽기


103

PowerShell에서 한 줄씩 파일을 읽고 싶습니다. 특히 파일을 반복하고 루프의 변수에 각 행을 저장하고 행에서 일부 처리를 수행하고 싶습니다.

나는 Bash에 해당하는 것을 알고 있습니다.

while read line do
    if [[ $line =~ $regex ]]; then
          # work here
    fi
done < file.txt

PowerShell 루프에 대한 문서는 많지 않습니다.


Mathias에서 선택한 답변은 훌륭한 솔루션이 아닙니다. Get-Content전체 파일을 한 번에 메모리로로드하므로 큰 파일에서는 실패하거나 멈 춥니 다.
Kolob Canyon

1
@KolobCanyon은 완전히 사실이 아닙니다. 기본적으로 Get-Content는 파이프 라인에서 각 줄을 하나의 개체로로드합니다. process블록을 지정하지 않는 함수 로 파이프를 연결하고 파이프 라인에 한 줄에 다른 개체를 뱉어내는 경우 해당 함수가 문제입니다. 전체 콘텐츠를 메모리에로드하는 데 문제가있는 것은의 잘못이 아닙니다 Get-Content.
The Fish

@TheFish foreach($line in Get-Content .\file.txt)반복을 시작하기 전에 전체 파일을 메모리에로드합니다. 저를 믿지 않으시면 1GB 로그 파일을 받아보십시오.
Kolob Canyon

2
@KolobCanyon 그건 당신이 말한 것이 아닙니다. Get-Content가 사실이 아닌 모든 것을 메모리에로드한다고 말씀하셨습니다. foreach의 변경된 예는 예입니다. foreach는 파이프 라인을 인식하지 않습니다. Get-Content .\file.txt | ForEach-Object -Process {}파이프 라인을 인식하며 전체 파일을 메모리로로드하지 않습니다. 기본적으로 Get-Content는 파이프 라인을 통해 한 번에 한 줄씩 전달합니다.
The Fish

답변:


180

PowerShell 루프에 대한 문서는 많지 않습니다.

PowerShell의 루프에 문서가 풍부하고, 다음 도움말 항목을 체크 아웃 할 수 있습니다 : about_For, about_ForEach, about_Do, about_While.

foreach($line in Get-Content .\file.txt) {
    if($line -match $regex){
        # Work here
    }
}

문제에 대한 또 다른 관용적 PowerShell 솔루션은 텍스트 파일의 줄을 ForEach-Objectcmdlet 으로 파이프하는 것입니다 .

Get-Content .\file.txt | ForEach-Object {
    if($_ -match $regex){
        # Work here
    }
}

루프 내에서 일치하는 정규식 대신에 Where-Object관심있는 라인 만 필터링하기 위해 라인을 파이프 할 수 있습니다.

Get-Content .\file.txt | Where-Object {$_ -match $regex} | ForEach-Object {
    # Work here
}

링크가 끊어지지는 않았지만 이제로 리디렉션됩니다 docs.microsoft.com.
Peter Mortensen

OP에서 문제로 언급되지 않은 @KolobCanyon.
The Fish

53

Get-Content성능이 좋지 않습니다. 한 번에 파일을 메모리로 읽어들이려고합니다.

C # (. NET) 파일 판독기는 각 줄을 하나씩 읽습니다.

최고의 공연

foreach($line in [System.IO.File]::ReadLines("C:\path\to\file.txt"))
{
       $line
}

또는 약간 덜 성능

[System.IO.File]::ReadLines("C:\path\to\file.txt") | ForEach-Object {
       $_
}

foreach진술은 약간 더 빠를 것입니다 ForEach-Object(자세한 내용은 아래 주석 참조).


5
나는 아마 [System.IO.File]::ReadLines("C:\path\to\file.txt") | ForEach-Object { ... }. 이 foreach문은 전체 컬렉션을 개체로로드합니다 . ForEach-Object파이프 라인을 사용하여 스트리밍합니다. 이제 foreach명령문은 ForEach-Object명령 보다 약간 더 빠를 수 있지만 일반적으로 전체를 메모리에로드하는 것이 더 빠르기 때문입니다. Get-Content그러나 여전히 끔찍합니다.
Bacon Bits

@BaconBits foreach()는 별칭입니다Foreach-Object
Kolob Canyon

16
그것은 매우 흔한 오해입니다. foreach성명,처럼 if, for또는 while. ForEach-Object같은 명령 Get-ChildItem입니다. foreachfor 의 기본 별칭도 ForEach-Object있지만 파이프 라인이있는 경우에만 사용됩니다. 에서 긴 설명을 Get-Help about_Foreach보거나 명령문과 명령의 차이점에 대한 Microsoft의 The Scripting Guys의 전체 기사로 이동하는 이전 댓글의 링크를 클릭하십시오.
Bacon Bits

4
@BaconBits blogs.technet.microsoft.com/heyscriptingguy/2014/07/08/… 새로운 것을 배웠습니다. 감사. 나는 그들이 동일한 때문에이었다 가정 Get-Alias foreach=> Foreach-Object,하지만 당신은 오른쪽 차이가 있습니다
계산법 캐년

2
그것은 작동하지만 당신은 변경할 수 있습니다 $line$_루프의 스크립트 블록에서.
Bacon Bits

1

만능 스위치는 여기에서 잘 작동합니다.

'one
two
three' > file

$regex = '^t'

switch -regex -file file { 
  $regex { "line is $_" } 
}

산출:

line is two
line is three
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.