자바스크립트를 활성화 해주세요

p048 PowerShell에서 Csv를 다루는 방법 정리

 ·  ☕ 6 min read

PowerShell에서 Csv를 다루는 방법 정리을 정리합니다. 이 내용은 알고리즘 문제를 풀 때도 데이터모델링할 때 사용하면 편합니다.

샘플 데이터에 대해서

이 포스트는 다음의 샘플데이터를 사용합니다.
이 파일은 UTF-8로 저장해 주세요.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'
$content = @"
"product_code","product_name","price"
"POSH00001","연필","100"
"POSH00002","지우개","50"
"POSH00003","노트","110"
"POSH00004","자","90"
"POSH00005","형광펜","70"
"@
$content > test.csv

csv 관련 Cmdlet의 개요

우선 csv 파일이나 csv 형식의 문자열과 PowerShell 객체로 변환하는 Cmdlet의 주기능은 다음에 설명하는 이 4가지 명령어 중 하나입니다.

  • ConvertFrom-Csv 문자열로 입력, PsCustomObject로 출력, 헤더 문자열을 배열로 지정
  • Import-Csv 파일로 입력, PsCustomObject로 출력, 헤더 문자열을 배열로 지정
  • ConvertTo-Csv PSCustom Object로 입력 문자열로 출력
  • Export-Csv PSCustom Object로 입력, 파일로 출력

간단히 말하면 파일을 조작할 때는 Import-Csv 과 Export-Csv 를 사용하고,
csv 형식의 문자열로 취급하고 싶을 때는 ConvertFrom-Csv 와 ConvertTo-Csv 를 사용합니다.

각 명령어의 사용 예

Import-Csv 과 Export-Csv

다음은 Import-Csv 즉 csv파일에서 PSCOstom Object로 변환하는 샘플입니다.
# TypeInfomation이 기재되어 있지 않기 때문에 csv 파일은 표준으로 PSCOstom Object로 변환됩니다.

1
2
$products = Import-Csv .\test.csv -Encoding UTF8
$products | Format-Table
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
PS C:\temp> $products = Import-Csv .\test.csv -Encoding UTF8

PS C:\temp> $products | Format-Table

product_code product_name price
------------ ------------ -----
POSH00001    연필           100  
POSH00002    지우개          50   
POSH00003    노트           110  
POSH00004                90   
POSH00005    형광펜          70   

PS C:\temp> $products[1].product_name
지우개

이번에는 그 반대로 PSCustom Object에서 csv 파일로 출력하는 샘플입니다.

$products = @(
  [pscustomobject]@{
    product_code = 'TEST00001'
    product_name = '볼펜'
    price = 100
  },
  [pscustomobject]@{
    product_code = 'TEST00002'
    product_name = '지우개'
    price = 50
  }
)

$products | Export-Csv -NoTypeInformation products.csv -Encoding UTF8

cat -Encoding UTF8 .\products.csv

결과

1
2
3
4
PS C:\temp> cat -Encoding UTF8 .\products.csv
"product_code","product_name","price"
"TEST00001","볼펜","100"
"TEST00002","지우개","50"

또한 JSON과 같은 포맷에서 PSCOstom Object를 생성하는 것이 편리한 경우에는 아래와 같은 방법도 있습니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
$products = @'
[
  {
    "product_code": "TEST00001",
    "product_name ": "볼펜",
    "price ": 100
  },
  {
    "product_code": "TEST00002",
    "product_name ": "지우개",
    "price ": 50
  }
]
'@ | ConvertFrom-Json

$products | Export-Csv -NoTypeInformation products.csv -Encoding UTF8

cat -Encoding UTF8 .\products.csv

결과

1
2
3
4
PS C:\temp> cat -Encoding UTF8 .\products.csv
"product_code","product_name ","price "
"TEST00001","볼펜","100"
"TEST00002","지우개","50"

ConvertFrom-Csv 와 Convert To-Csv

파일을 사용한 csv 입출력 조작이 가능하고 또 다음과 같이
단순히 문자열에서 PowerShell 오브젝트로 변환하는 방식으로도구현할 수 있습니다.

# csv 문자열에서 PowerShell 객체로 변환 샘플

1
2
3
4
5
6
7
8
$products = @'
"product_code","product_name ","price "
"TEST00001","볼펜","100"
"TEST00002","지우개","50"
'@ | ConvertFrom-Csv

$products
$products | ConvertTo-Csv -NoTypeInformation

결과

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
PS C:\temp> $products

product_code product_name  price 
------------ ------------- ------
TEST00001    볼펜            100   
TEST00002    지우개           50    

PS C:\temp> $products | ConvertTo-Csv -NoTypeInformation
"product_code","product_name ","price "
"TEST00001","볼펜","100"
"TEST00002","지우개","50"

각 옵션에 대해

NoTypeInformation 옵션

ConvertTo-Csv 과 Export-Csv로 출력해 낼 때 csv 데이터의 첫번째 행에 #TYPE 라는 주석으로 클래스 정보를 기재되게 됩니다.

다만 PowerShell6 이후에는 지정하든 하지 않든 #TYPE가 붙지 않게 된 것 같습니다.
(이제 NoTypeInformation 옵션의 의미가 없는듯..)

이 #TYPE라고 하는 주석의 형태로 타입정보를 써 두면, 다시 Import-Csv등에서 읽었을 때, Deserialize되나? 하고 생각을 했습니다만, 그렇지는 않습니다.

간혹 다른 언어로 CSV파일을 읽어들이면 오히려 에러가 나는 경우가 있으므로 항상 사용하는 것이 무난합니다.

Delimiter 옵션

구분자를 변경할 경우에는 Delimiter <char>를 사용하여 변경할 수 있습니다.
디폴트는 물론, 콤마입니다만, 탭문자 등으로 구분으로 하고 싶은 경우는 아래와 같이 사용합니다.

1
2
$products=Import-Csv.\products.csv-Encoding UTF8
$products | Convert To-Csv-Delimiter "`t"

Header 옵션

csv 형식의 데이터에 헤더 행이 없는 경우는 PowerShell 측에서 지정해야 합니다.

단순히 컬럼 순서에 맞춘 문자열 배열을 <Header <string[]> 로 넘기기만 하면 됩니다.

1
$products_csv | ConvertFrom-Csv -Header @('product_code', 'product_name', 'price')

덧붙여서 단순하게 1,2,3,… 와 같은 열 번호를 지정하는 경우가 좋을 때에는 다음과 같이 쓸 수 있습니다.

1
$products_csv | ConvertFrom-Csv-Header@(1..3)

메타 정보 다루기

컬럼별 타입정보 얻기

파일이나 문자열에서 읽어 들인 csv 데이터 컬럼을 확인하고 싶은 경우는, Get-Member 명령을 사용하면 구할 수 있습니다.
PowerShell 객체로 변환된 컬럼은 모두 string형으로 유지됩니다.

1
2
3
4
5
6
7
8
9
$products_csv = @'
"POSH00001","연필","100"
"POSH00002","지우개","50"
"POSH00003","노트","110"
"POSH00004","자","90"
"POSH00005","형광펜","70"
'@

$products | Get-Member -MemberType NoteProperty | select Name, Definition

결과

Name       Definition                     
----       ----------                     
Definition string Definition=int price=100
Name       string Name=price    

형변환

모든 컬럼이 string 그대로라면 불편하기 때문에, 적절한 형태로 변환해야할 때도 있습니다.
이 경우에는 다음과 같이 쓰면 변환이 가능합니다.

1
2
3
4
5
6
7
8
$products = $products_csv | 
    ConvertFrom-Csv -Header @('product_code', 'product_name', 'price') |
    ForEach-Object -Process {
        # 형변환
        $_.price = [int]($_.price)
        $_ # => Output
    }
$products

결과

product_code product_name price
------------ ------------ -----
POSH00001    연필             100
POSH00002    지우개             50
POSH00003    노트             110
POSH00004    자               90
POSH00005    형광펜             70

GridView로 보기

※ GridView 는 PowerShell 5 또는 PowerShell 7 이후에 사용 가능합니다.

가져온 csv 파일의 내용을 GUI 로 표시할 때 사용합니다만 가로 스크롤이 안되는 등의 문제가 있기 때문에, 늘 사용하지는 않습니다.

1
$products | ogv

p048_grid_view.png

덧붙여서, GridView 를 사용하면 GUI 조작에 의한 행의 추출도 가능합니다.

1
$low_price_products=$products | ogv -OutputMode Multiple

Out-GridView 명령에 -OutputModeMultiple을 지정한 뒤,
표시된 GridView 의 레코드를 선택하고 OK 버튼을 누르면, 행을 추출할 수 있습니다.

레퍼런스

공유하기

tkim
글쓴이
tkim
Software Engineer