PowerShell에서 대용량 텍스트 파일을 처리하는 방법(PowerShell에서 한 줄 로드하는 방법)

대상 독자


  • 사무 작업 등에서 PowerShell을 이용하여 데이터를 가공하고있는 사람
  • 중소 규모 시스템에서 운영 도구를 작성하는 사람 (특히 텍스트 로그를 처리하려는 경우 등)

  • 독자의 도달 목표



    PowerShell에서 프리즈 하는 대용량의 파일을, 프리즈 하지 않는 사이즈로 분할해 가공할 수 있게 되어 주셨으면 합니다.
    PowerShell을 처음부터 쓸 수 없는 분이라도 샘플 코드를 바탕으로 조작을 할 수 있도록 상세하게 기재했습니다.

    사건과 발생하는 문제, 해결해야 할 과제



    PowerShell에서 텍스트 파일을 읽은 경우 1MB 파일이라고해도
    메타 정보가 다수 부여됨으로써, 적당히 메모리를 소비해 버린다.

    이렇게 하면 수백 MB, 수 GB가 되면 OutOfMemory가 발생해도 처리할 수 있습니다.
    이를 해결하기 위해 PowerShell에서 대용량 파일을 처리하는 방법을 요약합니다.

    해결 방법



    위와 같은 경우에, 텍스트 파일을 모두 메모리에 로드해 버리면 에러가 되어 버립니다.
    따라서 파일을 한 줄씩 처리하고 행에서 얻은 정보 단위로 다시 분할하여
    처리 가능한 파일 크기를 처리합니다.

    다음은 샘플 코드입니다.
    검증 환경: Windows10 Powershell v5.1
    ※Windows PowerShell 포켓 레퍼런스에서는, v1~v3까지 대응하고 있으면
    기재되어 있으므로 v5까지의 모든 버젼으로 이용할 수 있을까 생각합니다.

    testData.csv
    国名,牛肉(くず肉含む)_第一単位,牛肉(くず肉含む)_第一数量,牛肉(くず肉含む)第二単位,牛肉(くず肉含む)_第二数量,牛肉(くず肉含む)_金額(千円),内牛肉(くず肉除く)_第一単位,内牛肉(くず肉除く)_第一数量,内牛肉(くず肉除く)_第二単位,内牛肉(くず肉除く)_第二数量,内牛肉(くず肉除く)_金額(千円),内牛肉(くず肉)_第一単位,内牛肉(くず肉)_第一数量,内牛肉(くず肉)_第二単位,内牛肉(くず肉)_第二数量,内牛肉(くず肉)_金額(千円)
    世界,,0,KG,41603500,27049397,,0,KG,41543781,27009997,,0,KG,59719,39400
    デンマーク,,0,KG,0,0,,0,KG,0,0,,0,KG,0,0
    アイルランド,,0,KG,23722,9577,,0,KG,23722,9577,,0,KG,0,0
    オランダ,,0,KG,5750,7436,,0,KG,5750,7436,,0,KG,0,0
    フランス,,0,KG,9393,19435,,0,KG,9095,19187,,0,KG,298,248
    イタリア,,0,KG,2724,5972,,0,KG,2724,5972,,0,KG,0,0
    ポーランド,,0,KG,0,0,,0,KG,0,0,,0,KG,0,0
    ハンガリー,,0,KG,0,0,,0,KG,0,0,,0,KG,0,0
    カナダ,,0,KG,657099,329262,,0,KG,657099,329262,,0,KG,0,0
    アメリカ合衆国,,0,KG,17741367,12157552,,0,KG,17741367,12157552,,0,KG,0,0
    メキシコ,,0,KG,957074,492920,,0,KG,957074,492920,,0,KG,0,0
    ニカラグア,,0,KG,0,0,,0,KG,0,0,,0,KG,0,0
    パナマ,,0,KG,6286,2689,,0,KG,6286,2689,,0,KG,0,0
    チリ,,0,KG,9862,8523,,0,KG,3003,4707,,0,KG,6859,3816
    オーストラリア,,0,KG,21341155,13308503,,0,KG,21288593,13273167,,0,KG,52562,35336
    ニュージーランド,,0,KG,849068,707528,,0,KG,849068,707528,,0,KG,0,0
    バヌアツ,,0,KG,0,0,,0,KG,0,0,,0,KG,0,0
    

    출처 : 정부 통계의 종합 창구 (e-Stat) (h tp // w w. 에 s t. . jp/)
    「무역 통계(수출) 1 농산물(축산품) 쇠고기」의 데이터를 취급하기 쉽도록 Excel 형식에서 CSV 형식으로 편집하고 있습니다.
    ※주 테스트 데이터용이므로 데이터 자체를 이용하고 싶은 경우는 원본을 취득해 주십시오.
    원본 URL (htps //w w. 에 s t. . jp / s t-sea rch / fu s? Page = 1 & Kue ry = % 7 % 89 % 9B % 8 % 82 % 89 & t = t & s t_ s t_ an fu d = 000031663012)

    LargeFileSplit.ps1
        $inputfile = ".\testData.txt"
        $outPath = ".\output\testData_after_"
        $extension = ".txt"
        Get-Content -ReadCount 1 $inputfile -Encoding UTF8 | ForEach-Object {
            $line = $_ -split ','
            $outfile = $outPath + $line[0] + $extension
            # 何かしらの編集処理 後で編集方法も整理したい
            Out-File $outfile -Encoding UTF8 -Append -NoClobber -InputObject $_
        }
    

    실행 결과


    테스트 데이터에서는, 1열째의 나라명을 취득해, 나라명 단위로 파일을 작성하고 있습니다.
    분할의 대상으로 하는 데이터는 적절히 선택해 주십시오.

    Get-Content의 옵션으로 이용하고 있는 「-ReadCount」가 포인트가 됩니다.
    이 옵션을 사용하면 파이프라인으로 보낼 행 수를 지정할 수 있습니다.
    ※1행으로 하지 않으면 형태가 바뀌어 버려, 데이터의 가공을 할 수 없게 됩니다.

    또한 Import-Csv에서는 이 옵션을 사용할 수 없으므로,
    샘플에서는, CSV 파일을 처리하는 경우를 고려해, 콤마 단락으로 데이터를 취득하는 방법으로 하고 있습니다.

    파일에 헤더를 부여하고 싶은 경우는, 이하와 같이 Test-Path에서
    파일의 유무를 확인하고, 없으면 파일을 만들어 헤더를 부여하는 것으로 대응합니다.

    LargeFileSplitKai.ps1
        $inputfile = ".\testData.txt"
        $outPath = ".\output\testData_after_"
        $extension = ".txt"
        Get-Content -ReadCount 1 $inputfile -Encoding UTF8 | ForEach-Object {
            $line = $_ -split ','
            $outfile = $outPath + $line[0] + $extension
            # 何かしらの編集処理
            # 下のif文で初回書き込みかチェックしヘッダをつけることも可能
            if(!(Test-Path -Path $outfile)){
                Out-File $outfile -Encoding UTF8 -Append -NoClobber -InputObject $header
            }
            Out-File $outfile -Encoding UTF8 -Append -NoClobber -InputObject $_  
        }
    

    참고



    참고로 이용한 링크, 서적을 기재합니다.

    링크



    MicroSoft의 Get-Content 참조
    e-Stat 정부 통계의 종합 창구



    Windows PowerShell 포켓 레퍼런스 무타구치 다이스케(저):기술 평론사

    좋은 웹페이지 즐겨찾기