배열
쉼표로 늘어놓으면 배열이다. 빈 배열이나 원소가 하나인 배열은 @()로 만든다.
$numbers = 10, 20, 30, 40, 50
$empty = @()
$one = @('only')
명령의 결과는 하나일 수도 여럿일 수도 있다. 결과가 하나면 배열이 아니라 그 개체 하나가 돌아온다. 늘 배열로 다루고 싶으면 @()로 감싼다.
$files = @(Get-ChildItem *.log)
$files.Count # 0개, 1개, 여러 개 어느 때나 맞는 값
꺼내고 자르기
번호는 0부터 세고, 음수는 뒤에서부터 센다. 범위나 여러 번호를 주면 잘라 낸다.
$numbers[0] # 10
$numbers[-1] # 50
$numbers[1..3] # 20 30 40
$numbers[-2..-1] # 40 50
$numbers[0, 2, 4] # 10 30 50
파이프라인 없이 거르고 바꾸는 메서드도 있다. 메모리에 이미 있는 배열에는 이쪽이 빠르다.
(1..10).Where({ $_ % 2 -eq 0 }) # 2 4 6 8 10
(1..3).ForEach({ $_ * 2 }) # 2 4 6
+= 는 느리다
배열은 크기가 고정이다. +=는 원소를 덧붙이는 것이 아니라 하나 더 큰 배열을 새로 만들어 전부 복사한다. 몇 개일 때는 상관없지만 반복문 안에서 수만 번 하면 차이가 크다. 숫자 2만 개를 모으는 데 걸린 시간을 재 봤다(PowerShell 7.6.6, 라즈베리 파이 5).
| 방법 | 걸린 시간 |
|---|---|
$a += $i | 1,275ms |
List[int]의 .Add() | 64ms |
| 반복문의 결과를 변수에 받기 | 42ms |
7.5에서 +=가 많이 빨라졌지만 여전히 가장 느리다. 가장 빠르고 PowerShell다운 방법은 반복문이 내놓는 값을 그대로 받는 것이다.
$result = foreach ($i in 1..20000) { $i * 2 }
중간에 넣고 빼야 하면 리스트를 쓴다.
$list = [System.Collections.Generic.List[string]]::new()
$list.Add('a')
$list.Remove('a')
해시 테이블
키와 값의 쌍이다. @{}로 만든다.
$server = @{
Name = 'web1'
Port = 443
}
$server.Name # web1
$server['Port'] # 443
$server.Region = 'kr' # 추가
$server.Remove('Port') # 삭제
$server.ContainsKey('Name')
키와 값을 돌 때는 GetEnumerator()를 쓴다.
foreach ($entry in $server.GetEnumerator()) {
"$($entry.Key) = $($entry.Value)"
}
순서가 필요하면 [ordered]
보통의 해시 테이블은 넣은 순서를 지키지 않는다. 순서가 중요하면 [ordered]를 붙인다.
$h = [ordered]@{ Name = 'talsu'; Lang = 'PowerShell' }
$h.Year = 2026
$h.Keys # Name Lang Year
해시 테이블과 개체
해시 테이블 앞에 [pscustomobject]를 붙이면 개체가 된다. 표로 보이고, 정렬하고, CSV로 내보낼 수 있다.
[pscustomobject]$h
Name Lang Year
---- ---- ----
talsu PowerShell 2026
둘을 가르는 기준은 이렇다. 찾아보는 용도(이름으로 값을 꺼낸다)면 해시 테이블, 한 건의 기록(여러 건을 모아 표로 다룬다)이면 개체.
JSON은 양쪽으로 오간다. -AsHashtable을 붙이면 개체 대신 해시 테이블로 받는다. 키에 공백이나 특수 문자가 든 JSON을 다룰 때 편하다.
$config = Get-Content ./config.json -Raw | ConvertFrom-Json -AsHashtable
$config | ConvertTo-Json -Depth 5 | Set-Content ./config.json
ConvertTo-Json은 기본으로 두 단계까지만 풀어 쓴다. 더 깊은 자료는 -Depth를 늘리지 않으면 잘린다.
묶어서 찾아보기
Group-Object -AsHashTable은 목록을 키로 찾아볼 수 있는 표로 바꾼다. 같은 목록을 여러 번 뒤져야 할 때 매번 Where-Object로 거르는 것보다 훨씬 빠르다.
$byExtension = Get-ChildItem $PSHOME -File | Group-Object Extension -AsHashTable
$byExtension['.json'].Name
스플래팅: 매개변수를 해시 테이블로
매개변수가 많아 줄이 길어지면 해시 테이블에 담아 @로 넘긴다.
$params = @{
Path = $PSHOME
Filter = '*.json'
File = $true
}
Get-ChildItem @params
줄을 잇는 백틱(`)을 쓰지 않아도 되고, 조건에 따라 매개변수를 넣고 빼기 쉽다.
if ($Recurse) { $params.Recurse = $true }
Get-ChildItem @params
다음 글: 함수와 매개변수