다른 많은 언어와 마찬가지로 PowerShell에는 스크립트 내에서 실행 흐름을 제어하는 명령이 있습니다. 이러한 명령문 중 하나는 switch 문이며 PowerShell에서는 다른 언어에서 찾을 수 없는 기능을 제공합니다. PowerShell switch
작업을 깊이 있게 살펴보는 오늘입니다.
비고
이 문서의 원래 버전@KevinMarquette작성한 블로그에 나타났습니다. PowerShell 팀은 이 콘텐츠를 공유해 주신 Kevin에게 감사드립니다. PowerShellExplained.com자신의 블로그를 확인하세요.
if
선언문
학습한 첫 번째 문 중 하나는 if
문입니다. 문장이 $true
인 경우 스크립트 블록을 실행할 수 있게 합니다.
if ( Test-Path $Path )
{
Remove-Item $Path
}
elseif
및 else
문을 사용하여 훨씬 더 복잡한 논리를 가질 수 있습니다. 다음은 요일의 숫자 값이 있고 이름을 문자열로 가져오는 예제입니다.
$day = 3
if ( $day -eq 0 ) { $result = 'Sunday' }
elseif ( $day -eq 1 ) { $result = 'Monday' }
elseif ( $day -eq 2 ) { $result = 'Tuesday' }
elseif ( $day -eq 3 ) { $result = 'Wednesday' }
elseif ( $day -eq 4 ) { $result = 'Thursday' }
elseif ( $day -eq 5 ) { $result = 'Friday' }
elseif ( $day -eq 6 ) { $result = 'Saturday' }
$result
Wednesday
이것은 일반적인 패턴이며 이를 처리하는 여러 가지 방법이 있습니다. 그 중 하나는 switch
을 가지고 있습니다.
Switch 문
switch
문을 사용하면 변수와 가능한 값 목록을 제공할 수 있습니다. 값이 변수와 일치하면 해당 scriptblock이 실행됩니다.
$day = 3
switch ( $day )
{
0 { $result = 'Sunday' }
1 { $result = 'Monday' }
2 { $result = 'Tuesday' }
3 { $result = 'Wednesday' }
4 { $result = 'Thursday' }
5 { $result = 'Friday' }
6 { $result = 'Saturday' }
}
$result
'Wednesday'
이 예제에서는 $day
값이 숫자 값 중 하나와 일치한 다음 올바른 이름이 $result
할당됩니다. 이 예제에서는 변수 할당만 수행하지만 해당 스크립트 블록에서 PowerShell을 실행할 수 있습니다.
변수에 할당
마지막 예제를 다른 방법으로 작성할 수 있습니다.
$result = switch ( $day )
{
0 { 'Sunday' }
1 { 'Monday' }
2 { 'Tuesday' }
3 { 'Wednesday' }
4 { 'Thursday' }
5 { 'Friday' }
6 { 'Saturday' }
}
PowerShell 파이프라인에 값을 배치하고 $result
에 값을 할당합니다.
if
및 foreach
문을 사용하여 이 작업을 수행할 수 있습니다.
기본값
default
키워드를 사용하여 일치하는 항목이 없는 경우 발생할 작업을 식별할 수 있습니다.
$result = switch ( $day )
{
0 { 'Sunday' }
# ...
6 { 'Saturday' }
default { 'Unknown' }
}
여기서는 기본 사례에서 Unknown
값을 반환합니다.
현악기들
마지막 예제에서 숫자를 일치시켰지만, 문자열을 일치시킬 수도 있습니다.
$item = 'Role'
switch ( $item )
{
Component
{
'is a component'
}
Role
{
'is a role'
}
Location
{
'is a location'
}
}
is a role
나는 Component
,Role
, Location
일치를 따옴표로 묶지 않기로 결정했으며, 이는 그것들이 선택 사항임을 강조하기 위함입니다.
switch
대부분의 경우 문자열로 처리합니다.
배열
PowerShell switch
멋진 기능 중 하나는 배열을 처리하는 방법입니다.
switch
배열을 지정하면 해당 컬렉션의 각 요소를 처리합니다.
$roles = @('WEB','Database')
switch ( $roles ) {
'Database' { 'Configure SQL' }
'WEB' { 'Configure IIS' }
'FileServer' { 'Configure Share' }
}
Configure IIS
Configure SQL
배열에 반복된 항목이 있는 경우 해당 섹션에 의해 여러 번 일치합니다.
PSItem
$PSItem
또는 $_
사용하여 처리된 현재 항목을 참조할 수 있습니다. 간단한 일치를 수행할 때 $PSItem
일치하는 값입니다. 이 변수가 사용되는 다음 섹션에서 몇 가지 고급 일치를 수행합니다.
매개 변수
PowerShell switch
고유한 기능은 성능 방식을 변경하는 여러 스위치 매개 변수가 있다는 것입니다.
-대소문자 구분
일치 항목은 기본적으로 대/소문자를 구분하지 않습니다. 대/소문자를 구분해야 하는 경우 -CaseSensitive
사용할 수 있습니다. 다른 스위치 매개 변수와 함께 사용할 수 있습니다.
-와일드 카드
-Wildcard
스위치를 사용하여 와일드카드 지원을 사용하도록 설정할 수 있습니다.
-like
연산자로 동일한 와일드카드 논리를 사용하여 각 일치를 수행합니다.
$Message = 'Warning, out of disk space'
switch -Wildcard ( $message )
{
'Error*'
{
Write-Error -Message $Message
}
'Warning*'
{
Write-Warning -Message $Message
}
default
{
Write-Information $message
}
}
WARNING: Warning, out of disk space
여기서는 메시지를 처리한 다음 내용에 따라 다른 스트림에 출력합니다.
-Regex
switch 문은 와일드카드와 마찬가지로 정규식 일치를 지원합니다.
switch -Regex ( $message )
{
'^Error'
{
Write-Error -Message $Message
}
'^Warning'
{
Write-Warning -Message $Message
}
default
{
Write-Information $message
}
}
내가 쓴 다른 문서에서 regex를 사용하는 더 많은 예가 있습니다 : regex사용하는 여러 가지 방법입니다.
-파일
switch 문의 잘 알려지지 않은 기능은 그것이 -File
매개 변수를 사용하여 파일을 처리할 수 있다는 것입니다. 변수 식을 제공하는 대신 파일 경로와 함께 -File
사용합니다.
switch -Wildcard -File $path
{
'Error*'
{
Write-Error -Message $PSItem
}
'Warning*'
{
Write-Warning -Message $PSItem
}
default
{
Write-Output $PSItem
}
}
배열을 처리하는 것처럼 작동합니다. 이 예제에서는 와일드카드 일치와 결합하고 $PSItem
사용합니다. 이렇게 하면 로그 파일이 처리되고 regex 일치 항목에 따라 경고 및 오류 메시지로 변환됩니다.
고급 세부 정보
이제 이러한 문서화된 모든 기능을 인식했으므로 고급 처리의 컨텍스트에서 사용할 수 있습니다.
표현식
switch
변수 대신 식에 있을 수 있습니다.
switch ( ( Get-Service | where Status -EQ 'running' ).Name ) {...}
식이 평가되어 나온 값은 일치 항목에 사용되는 값입니다.
여러 일치 항목
아마도 이미 알아차렸겠지만, switch
는 여러 조건과 일치할 수 있습니다.
-Wildcard
또는 -Regex
일치 항목을 사용하는 경우 특히 그렇습니다. 동일한 조건을 여러 번 추가할 수 있으며 모두 트리거됩니다.
switch ( 'Word' )
{
'word' { 'lower case word match' }
'Word' { 'mixed case word match' }
'WORD' { 'upper case word match' }
}
lower case word match
mixed case word match
upper case word match
이 세 가지 주장은 모두 무효화되었습니다. 이는 모든 조건이 차례대로 검토되었음을 보여 줍니다. 각 항목이 각 조건을 확인하는 배열을 처리하는 경우 이는 참입니다.
계속
일반적으로 break
문을 소개하는 곳이지만 먼저 continue
사용하는 방법을 배우는 것이 좋습니다.
foreach
루프와 마찬가지로 continue
컬렉션의 다음 항목으로 계속 이동하거나 항목이 더 이상 없으면 switch
종료합니다. 마지막 예제를 continue 문으로 다시 작성하여 하나의 문만 실행할 수 있습니다.
switch ( 'Word' )
{
'word'
{
'lower case word match'
continue
}
'Word'
{
'mixed case word match'
continue
}
'WORD'
{
'upper case word match'
continue
}
}
lower case word match
세 항목을 모두 일치시키는 대신 첫 번째 항목이 일치하고 스위치가 다음 값으로 계속됩니다. 처리할 값이 없으므로 스위치가 종료됩니다. 다음 예제에서는 와일드카드가 여러 항목과 일치할 수 있는 방법을 보여 줍니다.
switch -Wildcard -File $path
{
'*Error*'
{
Write-Error -Message $PSItem
continue
}
'*Warning*'
{
Write-Warning -Message $PSItem
continue
}
default
{
Write-Output $PSItem
}
}
입력 파일의 줄에 Error
단어와 Warning
모두 포함될 수 있으므로 첫 번째 줄만 실행한 다음 파일 처리를 계속하려고 합니다.
휴식
break
문장이 switch 문에서 빠져나옵니다. 이는 continue
단일 값에 대해 제시하는 것과 동일한 동작입니다. 배열을 처리할 때 차이가 표시됩니다.
break
스위치의 모든 처리를 중지하고 continue
다음 항목으로 이동합니다.
$Messages = @(
'Downloading update'
'Ran into errors downloading file'
'Error: out of disk space'
'Sending email'
'...'
)
switch -Wildcard ($Messages)
{
'Error*'
{
Write-Error -Message $PSItem
break
}
'*Error*'
{
Write-Warning -Message $PSItem
continue
}
'*Warning*'
{
Write-Warning -Message $PSItem
continue
}
default
{
Write-Output $PSItem
}
}
Downloading update
WARNING: Ran into errors downloading file
Write-Error -Message $PSItem : Error: out of disk space
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException
이 경우 Error
시작하는 줄에 도달하면 오류가 발생하며 스위치가 중지됩니다.
이것이 바로 break
진술이 우리를 위해 하는 일입니다. 문자열에서 Error
이 처음에만 있는 것이 아니라 내부에 발견되면 경고로 기록합니다. 우리는 Warning
대해 같은 일을합니다. 줄에는 Error
과 Warning
두 단어가 모두 있을 수 있지만, 처리에는 둘 중 하나만 필요합니다. 이것이 continue
진술이 우리를 위해 하는 일입니다.
레이블 중단
switch
문은 break/continue
레이블을 foreach
처럼 지원합니다.
:filelist foreach($path in $logs)
{
:logFile switch -Wildcard -File $path
{
'Error*'
{
Write-Error -Message $PSItem
break filelist
}
'Warning*'
{
Write-Error -Message $PSItem
break logFile
}
default
{
Write-Output $PSItem
}
}
}
개인적으로는 브레이크 레이블의 사용을 좋아하지 않지만, 그것들을 이전에 본 적이 없다면 혼란스러울 수 있어 지적하고 싶었습니다. 중첩된 switch
또는 foreach
문이 여러 개 있는 경우 가장 안쪽 항목보다 더 많은 항목을 분리할 수 있습니다.
switch
에 레이블을 붙여 break
의 대상으로 만들 수 있습니다.
열거형
PowerShell 5.0은 열거형을 도입했으며, 이를 스위치에서 사용할 수 있습니다.
enum Context {
Component
Role
Location
}
$item = [Context]::Role
switch ( $item )
{
Component
{
'is a component'
}
Role
{
'is a role'
}
Location
{
'is a location'
}
}
is a role
모든 항목을 강력한 형식의 열거형으로 유지하려는 경우 괄호 안에 배치할 수 있습니다.
switch ($item )
{
([Context]::Component)
{
'is a component'
}
([Context]::Role)
{
'is a role'
}
([Context]::Location)
{
'is a location'
}
}
여기서는 스위치가 [Context]::Location
값을 리터럴 문자열로 처리하지 않도록 괄호가 필요합니다.
ScriptBlock
필요한 경우 scriptblock을 사용하여 일치 항목에 대한 평가를 수행할 수 있습니다.
$age = 37
switch ( $age )
{
{$PSItem -le 18}
{
'child'
}
{$PSItem -gt 18}
{
'adult'
}
}
'adult'
이렇게 하면 복잡성이 추가되고 switch
읽기 어려울 수 있습니다. 이와 같은 항목을 사용하는 대부분의 경우 if
및 elseif
문을 사용하는 것이 좋습니다. 이미 대형 스위치가 설치되어 있고 동일한 평가 블록에 도달하기 위해 두 항목이 필요한 경우 이를 고려할 것입니다.
가독성에 도움이 된다고 생각하는 한 가지는 scriptblock을 괄호 안에 배치하는 것입니다.
switch ( $age )
{
({$PSItem -le 18})
{
'child'
}
({$PSItem -gt 18})
{
'adult'
}
}
여전히 동일한 방식으로 실행되며, 빠르게 살펴볼 때 시각적으로 더 잘 구분됩니다.
Regex $Matches
우리는 즉시 명확하지 않은 무언가를 다루기 위해 정규 표현식을 다시 살펴봐야 합니다. regex를 사용하면 $Matches
변수가 채워집니다. 내가 에 대해 이야기할 때 $Matches
의 사용법을 더 설명하며 regex를에서 사용하는 여러 가지 방법에 대해 이야기합니다. 명칭을 정한 매칭의 작동을 보여주는 간단한 샘플입니다.
$message = 'my ssn is 123-23-3456 and credit card: 1234-5678-1234-5678'
switch -Regex ($message)
{
'(?<SSN>\d\d\d-\d\d-\d\d\d\d)'
{
Write-Warning "message contains a SSN: $($Matches.SSN)"
}
'(?<CC>\d\d\d\d-\d\d\d\d-\d\d\d\d-\d\d\d\d)'
{
Write-Warning "message contains a credit card number: $($Matches.CC)"
}
'(?<Phone>\d\d\d-\d\d\d-\d\d\d\d)'
{
Write-Warning "message contains a phone number: $($Matches.Phone)"
}
}
WARNING: message may contain a SSN: 123-23-3456
WARNING: message may contain a credit card number: 1234-5678-1234-5678
$null
기본값이 될 필요가 없는 $null
값을 일치시킬 수 있습니다.
$values = '', 5, $null
switch ( $values )
{
$null { "Value '$_' is `$null" }
{ '' -eq $_ } { "Value '$_' is an empty string" }
default { "Value [$_] isn't an empty string or `$null" }
}
Value '' is an empty string
Value [5] isn't an empty string or $null
Value '' is $null
switch
문에서 빈 문자열을 테스트할 때는 원시 값 ''
대신 이 예제와 같이 비교 문을 사용해야 합니다.
switch
문에서 원시 값 ''
이 $null
와 일치합니다. 다음은 그 예입니다.
$values = '', 5, $null
switch ( $values )
{
$null { "Value '$_' is `$null" }
'' { "Value '$_' is an empty string" }
default { "Value [$_] isn't an empty string or `$null" }
}
Value '' is an empty string
Value [5] isn't an empty string or $null
Value '' is $null
Value '' is an empty string
또한 cmdlet의 빈 반환에 주의해야 합니다. 출력이 없는 cmdlet 또는 파이프라인은 default
사례를 포함하여 아무것도 일치하지 않는 빈 배열로 처리됩니다.
$file = Get-ChildItem NonExistantFile*
switch ( $file )
{
$null { '$file is $null' }
default { "`$file is type $($file.GetType().Name)" }
}
# No matches
상수 식
Lee Dailey는 상수 $true
식을 사용하여 [bool]
항목을 평가할 수 있다고 지적했습니다.
여러 개의 부울 검사가 필요하다고 가정해 보십시오.
$isVisible = $false
$isEnabled = $true
$isSecure = $true
switch ( $true )
{
$isEnabled
{
'Do-Action'
}
$isVisible
{
'Show-Animation'
}
$isSecure
{
'Enable-AdminMenu'
}
}
Do-Action
Enabled-AdminMenu
이는 여러 부울 필드의 상태를 평가하고 조치를 취하는 깨끗한 방법입니다. 이에 대한 멋진 점은 하나의 일치 항목이 아직 평가되지 않은 값의 상태를 뒤집을 수 있다는 것입니다.
$isVisible = $false
$isEnabled = $true
$isAdmin = $false
switch ( $true )
{
$isEnabled
{
'Do-Action'
$isVisible = $true
}
$isVisible
{
'Show-Animation'
}
$isAdmin
{
'Enable-AdminMenu'
}
}
Do-Action
Show-Animation
이 예제에서 $isEnabled
를 $true
으로 설정하면 $isVisible
도 $true
으로 설정되도록 합니다.
그런 다음 $isVisible
평가되면 해당 scriptblock이 호출됩니다. 이것은 약간 직관적이지 않지만 역학을 영리하게 사용합니다.
자동 변수 $switch
switch
값을 처리할 때 열거자를 만들고 $switch
호출합니다. PowerShell에서 만든 자동 변수이며 직접 조작할 수 있습니다.
$a = 1, 2, 3, 4
switch($a) {
1 { [void]$switch.MoveNext(); $switch.Current }
3 { [void]$switch.MoveNext(); $switch.Current }
}
그러면 다음과 같은 결과가 표시됩니다.
2
4
열거자를 앞으로 이동하면 다음 항목이 switch
처리되지 않지만 해당 값에 직접 액세스할 수 있습니다. 나는 그것을 광기라고 부를 것이다.
기타 패턴
해시 테이블
내 가장 인기 있는 게시물 중 하나는 내가 해시 테이블에 대해 다룬 것입니다.
hashtable
사용 사례 중 하나는 조회 테이블이 되는 것입니다. 이는 switch
문이 자주 다루는 일반적인 패턴에 대한 대체 방법입니다.
$day = 3
$lookup = @{
0 = 'Sunday'
1 = 'Monday'
2 = 'Tuesday'
3 = 'Wednesday'
4 = 'Thursday'
5 = 'Friday'
6 = 'Saturday'
}
$lookup[$day]
Wednesday
switch
를 단순 조회로만 사용할 경우, 대신 hashtable
을 사용하는 경우가 많습니다.
열거형
PowerShell 5.0은 enum
도입했으며 이 경우에도 옵션입니다.
$day = 3
enum DayOfTheWeek {
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
}
[DayOfTheWeek]$day
Wednesday
우리는 하루 종일이 문제를 해결하는 다른 방법을 찾고 갈 수 있습니다. 난 그냥 당신이 옵션이 있다는 것을 알고 있는지 확인하고 싶었다.
마지막 단어
스위치 문은 표면에서 간단하지만 대부분의 사람들이 인식하지 못하는 몇 가지 고급 기능을 제공합니다. 이러한 기능을 함께 묶으면 강력한 기능이 됩니다. 난 당신이 전에 실현하지 않은 무언가를 배웠으면 좋겠다.
PowerShell