PowerShell의 삼항 연산자


214

내가 아는 바에 따르면 PowerShell에는 소위 삼항 연산자에 대한 기본 제공식이없는 것 같습니다 .

예를 들어, 삼항 연산자를 지원하는 C 언어에서는 다음과 같이 작성할 수 있습니다.

<condition> ? <condition-is-true> : <condition-is-false>;

이것이 PowerShell에 실제로 존재하지 않는다면 동일한 결과를 달성하는 가장 좋은 방법은 무엇입니까 (즉, 읽고 유지 관리하기 쉬운가)?


5
github.com/nightroman/PowerShellTraps/tree/master/Basic/… 를 보십시오 . 이것이 당신이 찾고있는 것이라면 나는 그것을 대답 할 수 있습니다.
— Roman Kuzmin

2
그것은의 조건 운영자 또는 삼항 경우 . "삼항 연산자"는 아닙니다. 모든 의미는 세 개의 인수를 취하는 연산자 ( 모든 연산자)이기 때문입니다.
— Damien_The_Unbeliever

7
@Damien_The_Unbeliever 기술적으로는 사실이지만 종종 삼항 연산자라고합니다. 삼항 연산자 "이 연산자는 언어에서 유일하게 기존의 삼항 연산자는 종종이기 때문에, 때로는 단순히라고"조건 연산자 ""일부 언어에서는이 연산자라고합니다. ". 삼항 작동
— mguassa

Visual Basic에는 실제 삼항 연산자가 없지만 IF와 IFF는 기능적으로 동등한 것으로 간주합니다.
— Matt

@Matt 잘못되었습니다. 이 IIF 함수 는 항상 두 피연산자를 모두 평가합니다. If문은하지 않습니다 - 참조 stackoverflow.com/questions/1220411/...을 (새로운 VB.NET 버전은 삼항 표현 추가 If (x, y, z))
— user2864740

답변:


319
$result = If ($condition) {"true"} Else {"false"}

그 밖의 모든 것은 부수적으로 복잡하므로 피해야합니다.

할당뿐만 아니라 표현식으로 또는 표현식으로 사용하려면 다음과 같이 묶으십시오 $().

write-host  $(If ($condition) {"true"} Else {"false"}) 

3
그것은 등호의 오른쪽에서 작동하지만 삼항 연산자를 기대하지는 않지만 "a"+ If ($ condition) { "true"} 그렇지 않으면 { "false"} 및 "a"+ (If ($ condition) { "true"} Else { "false"}) 작동합니다 (아직 확실하지 않은 이유) : "a"+ $ (If ($ condition) { "true"} Else { "false "})
— Lamarth

12
@Lamarth- $()래퍼가 명령문의 평가를 표현식으로 강제 실행하므로 삼항 연산자가 예상하는 것처럼 거짓 값의 실제 값을 리턴하므로 작동합니다. PowerShell AFAIK에서 가장 가까운 곳입니다.
— KeithS

4
다른 "비 기능"몇 가지 답변과는 달리,이 것 또한 하나의 지점이 실행되어 있는지 확인합니다.
— user2864740

63

에뮬레이션하기 위해 내가 찾은 가장 가까운 PowerShell 구성은 다음과 같습니다.

@({'condition is false'},{'condition is true'})[$condition]

15
({true}, {false})[!$condition]약간 더 낫다 (아마도) : a) 참과 거짓 부분의 전통적인 순서; b) $condition0 또는 1 또는 $ false, $ true 일 필요는 없습니다. 연산자 !는 필요에 따라 변환합니다. 즉 $condition42 :! 42 ~ $ false ~ 0 ~ 첫 번째 표현 일 수 있습니다.
— Roman Kuzmin

1
@RomanKuzmin과 동일하지 않습니다. mjolinor의 예제는 문자열을 반환합니다. 그러나 표현식에 연결된 그의 예제와 동일한 문자열 값은 스크립트 블록을 반환합니다. :-(
— Michael Sorens

5
으로 {true}하고 {false}내 말은 <true expression>하고 <false expression>,하지 스크립트 블록을. 정확하지 않아 죄송합니다.
— Roman Kuzmin

1
설명을 해주셔서 감사합니다. @RomanKuzmin – 현재 귀하의 제안에 가치가 있습니다.
— Michael Sorens

12
이렇게하면 왼쪽 및 오른쪽 옵션을 열심히 평가해야합니다. 이는 적절한 3 진 작업과는 매우 다릅니다.
— user2864740


24

이 PowerShell 블로그 게시물 에 따라 ?:운영자 를 정의하는 별칭을 만들 수 있습니다 .

set-alias ?: Invoke-Ternary -Option AllScope -Description "PSCX filter alias"
filter Invoke-Ternary ([scriptblock]$decider, [scriptblock]$ifTrue, [scriptblock]$ifFalse) 
{
   if (&$decider) { 
      &$ifTrue
   } else { 
      &$ifFalse 
   }
}

다음과 같이 사용하십시오.

$total = ($quantity * $price ) * (?:  {$quantity -le 10} {.9} {.75})

'결정자'가 스크립트 블록 인 이유는 없습니다. ?:평가 된 경우 인수를 평가해야합니다. 스크립트 블록이 없으면 유사한 사용법을 갖게됩니다 (예 : (?: ($quantity -le 10) {.9} {.75})
— user2864740

멋진 기능이지만 스크립트를 비표준으로 렌더링 할 수 있습니다. 예를 들어 별칭 정의도 함께 포팅하지 않으면 스크립트 또는 스크립트의 일부가 포트되지 않을 수 있습니다. 이 시점에서 기본적으로 고유 한 하위 언어를 작성하고 있습니다. 이 모든 것이 복잡성 증가와 가독성 감소로 인해 유지 관리 비용이 증가 할 수 있습니다.
— Vance McCorkle

1
@VanceMcCorkle 솔리드 포인트. 사용자 정의 간결함은 종종 유용하다면 그 가치가 있습니다. 그러나 상황이 거의 발생하지 않으면 "if"표현을 고수합니다.
— Edward Brey

21

나도 더 나은 답변을 찾고 Edward의 게시물에있는 해결책이 "ok"인 동안이 블로그 게시물에 훨씬 더 자연스러운 해결책을 찾았 습니다.

짧고 달다:

# ---------------------------------------------------------------------------
# Name:   Invoke-Assignment
# Alias:  =
# Author: Garrett Serack (@FearTheCowboy)
# Desc:   Enables expressions like the C# operators: 
#         Ternary: 
#             <condition> ? <trueresult> : <falseresult> 
#             e.g. 
#                status = (age > 50) ? "old" : "young";
#         Null-Coalescing 
#             <value> ?? <value-if-value-is-null>
#             e.g.
#                name = GetName() ?? "No Name";
#             
# Ternary Usage:  
#         $status == ($age > 50) ? "old" : "young"
#
# Null Coalescing Usage:
#         $name = (get-name) ? "No Name" 
# ---------------------------------------------------------------------------

# returns the evaluated value of the parameter passed in, 
# executing it, if it is a scriptblock   
function eval($item) {
    if( $item -ne $null ) {
        if( $item -is "ScriptBlock" ) {
            return & $item
        }
        return $item
    }
    return $null
}

# an extended assignment function; implements logic for Ternarys and Null-Coalescing expressions
function Invoke-Assignment {
    if( $args ) {
        # ternary
        if ($p = [array]::IndexOf($args,'?' )+1) {
            if (eval($args[0])) {
                return eval($args[$p])
            } 
            return eval($args[([array]::IndexOf($args,':',$p))+1]) 
        }

        # null-coalescing
        if ($p = ([array]::IndexOf($args,'??',$p)+1)) {
            if ($result = eval($args[0])) {
                return $result
            } 
            return eval($args[$p])
        } 

        # neither ternary or null-coalescing, just a value  
        return eval($args[0])
    }
    return $null
}

# alias the function to the equals sign (which doesn't impede the normal use of = )
set-alias = Invoke-Assignment -Option AllScope -Description "FearTheCowboy's Invoke-Assignment."

다음과 같은 작업을 쉽게 수행 할 수 있습니다 (블로그 게시물의 더 많은 예).

$message == ($age > 50) ? "Old Man" :"Young Dude" 

1
이것은 굉장합니다. C # 및 등식 검사를 위해 다른 많은 언어에서 사용 =되기 때문에 별칭으로 사용 하는 것을 좋아하지 않습니다 ==. C #에서 약간의 경험이있는 것은 파워 쉘러에게 매우 일반적이며 결과 코드를 약간 혼란스럽게 만듭니다. :아마도 더 나은 별칭 일 것입니다. 변수 할당과 함께 사용하면 =:Pascal에서 사용 된 할당을 생각 나게 할 수 있지만 VB.NET 또는 C #에서 즉각적으로 동등한 것을 가지고 있지는 않습니다.
— nohwnd

원하는 별칭으로 설정할 수 있습니다. : 또는 ~보트에 떠 다니는 것이 무엇이든. : D set-alias : Invoke-Assignment -Option AllScope -Description "FearTheCowboy's Invoke-Assignment." # 삼항 $message =: ($age > 50) ? "Old Man" :"Young Dude" # null 병합 $message =: $foo ?? "foo was empty"`
— 개럿 Serack

나는 다른 별칭을 사용하는 이유에 대해서만 언급하고있었습니다.
— nohwnd

15

Powershell의 switch 문을 대안으로 사용하십시오. 특히 변수 할당-여러 줄이지 만 읽을 수 있습니다.

예,

$WinVer = switch ( Test-Path $Env:windir\SysWOW64 ) {
  $true    { "64-bit" }
  $false   { "32-bit" }
}
"This version of Windows is $WinVer"

1
이것은 좀 더 장황 할 수 있지만 다른 많은 답변에 비해 상당한 이점이 있습니다. 특히 외부 코드 나 스크립트 나 모듈에 복사 / 붙여 넣기 기능에 의존하지 않습니다.
— bshacklett

9

삼항 연산자는 일반적으로 값을 지정할 때 사용되므로 값을 반환해야합니다. 이것이 작동하는 방법입니다.

$var=@("value if false","value if true")[[byte](condition)]

멍청하지만 작동합니다. 또한이 구성을 사용하여 int를 다른 값으로 빠르게 바꿀 수 있습니다. 배열 요소를 추가하고 0부터 시작하는 음이 아닌 값을 반환하는 식을 지정하십시오.


6
이렇게하면 왼쪽 및 오른쪽 옵션을 열심히 평가해야합니다. 이는 적절한 3 진 작업과는 매우 다릅니다.
— user2864740

6

이미 여러 번 사용했지만 여기에 나열되지 않았으므로 내 조각을 추가합니다.

$var = @{$true="this is true";$false="this is false"}[1 -eq 1]

가장 추한!

좀 소스


4
이렇게하면 왼쪽 및 오른쪽 옵션을 열심히 평가해야합니다. 이는 적절한 3 진 작업과는 매우 다릅니다.
— user2864740

@ user2864740은 PS에 적절한 삼항 연산이 없기 때문입니다. 이것은 합성 변형입니다.
— Viggo Lundén

2
적절한 삼항 연산자의 @ ViggoLundén 부족은 주석의 정확성을 감소시키지 않습니다. 이 "합성 변형" 은 다른 동작을 합니다.
— user2864740

당신 말이 맞아요. 당신의 의견을 다시 읽은 후에 어떻게 그것이 실제로 차이를 만들 수 있는지 이해합니다. 감사.
— sodawillow

5

최근에 PoweShell 라이브러리 'Pscx'Pls의 삼항 조건부 및 null 병합 연산자를 개선 (Open PullRequest)했습니다
. 내 솔루션을 찾습니다.


내 github 주제 브랜치 : UtilityModule_Invoke-Operators

기능 :

Invoke-Ternary
Invoke-TernaryAsPipe
Invoke-NullCoalescing
NullCoalescingAsPipe

별명

Set-Alias :?:   Pscx\Invoke-Ternary                     -Description "PSCX alias"
Set-Alias ?:    Pscx\Invoke-TernaryAsPipe               -Description "PSCX alias"
Set-Alias :??   Pscx\Invoke-NullCoalescing              -Description "PSCX alias"
Set-Alias ??    Pscx\Invoke-NullCoalescingAsPipe        -Description "PSCX alias"

용법

<condition_expression> |?: <true_expression> <false_expression>

<variable_expression> |?? <alternate_expression>

표현식으로
$ null, 리터럴, 변수, '외부'표현식 ($ b -eq 4) 또는 스크립트 블록 {$ b -eq 4}을 전달할 수 있습니다.

변수 표현식의 변수가 $ null이거나 존재하지 않는 경우 대체 표현식은 출력으로 평가됩니다.


4

PowerShell에는 현재 기본 인라인 If (또는 삼항 If )가 없지만 사용자 지정 cmdlet을 사용하는 것이 좋습니다.

IIf <condition> <condition-is-true> <condition-is-false>
참고 : PowerShell 인라인 If (IIf)


링크 된 포스트 쇼 방법을 만들IIf 기능을. 그러나 표준 PowerShell IIf기능 / cmdlet 은 없습니다 .
— user2864740

1
@ user2864740, 그럼 무엇? 그 질문에 대한 가능한 대답으로 답을 배제 하는가? "같은 결과를 달성하는 가장 좋은 방법은 무엇입니까? 그러나 그 점을 제외하면, 링크는 이것과 매우 유사한 IIf 질문 (9 월 5 일 게시)을 나타냅니다 (중복?). 연결된 질문의 나머지 답변은 부가 가치로 볼 수도 있습니다 (그렇지 않은 경우 주로 중복되기 때문에).
— iRon

약간의 설명은 먼 길 을 갔으므로 추가 정보가 추가되지 않은 경우 복제본을 닫지 않으므로 베어 링크 를 사용하지 않는 것이 좋습니다. 아주 작은 설명은 이러한 베어 링크 답변 의 품질을 크게 향상시킬 것입니다 . "Powershell은 직접 '삼항'을 지원하지 않습니다 (^하지만 다른 답변 참조). 그러나 이 방법, 또는 "..) 다른 답변을 참조하지만 그건 아니에요 내 추가하는 작업. 해당되는 경우 답변을 수정 / 업데이트 할 수 있습니다.
— user2864740

@ user2864740, 의견을 보내 주셔서 감사합니다. 이에 따라 답변을 조정했습니다.
— iRon

1

대체 사용자 정의 함수 접근 방식은 다음과 같습니다.

function Test-TernaryOperatorCondition {
    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline = $true, Mandatory = $true)]
        [bool]$ConditionResult
        ,
        [Parameter(Mandatory = $true, Position = 0)]
        [PSObject]$ValueIfTrue
        ,
        [Parameter(Mandatory = $true, Position = 1)]
        [ValidateSet(':')]
        [char]$Colon
        ,
        [Parameter(Mandatory = $true, Position = 2)]
        [PSObject]$ValueIfFalse
    )
    process {
        if ($ConditionResult) {
            $ValueIfTrue
        }
        else {
            $ValueIfFalse
        }
    }
}
set-alias -Name '???' -Value 'Test-TernaryOperatorCondition'

예

1 -eq 1 |??? 'match' : 'nomatch'
1 -eq 2 |??? 'match' : 'nomatch'

차이점 설명

  • 왜 1이 아닌 3 개의 물음표입니까?
    • ?문자는 이미 별칭입니다 Where-Object.
    • ?? 다른 언어에서는 null 병합 연산자로 사용되며 혼란을 피하고 싶었습니다.
  • 명령 전에 파이프가 필요한 이유는 무엇입니까?
    • 파이프 라인을 사용하여이를 평가하므로 조건을 함수에 파이프하려면 여전히이 문자가 필요합니다.
  • 배열을 전달하면 어떻게됩니까?
    • 각 값에 대한 결과를 얻습니다. 즉 -2..2 |??? 'match' : 'nomatch'제공 : match, match, nomatch, match, match(예를에 0이 아닌 INT 평가하여 이후 true제로 동안 평가하여 대상을 false).
    • 원하지 않으면 배열을 부울로 변환하십시오. ([bool](-2..2)) |??? 'match' : 'nomatch'(또는 단순히 : [bool](-2..2) |??? 'match' : 'nomatch')

1

부울 조건에 따라 문자열 또는 숫자를 할당 / 반환하는 구문 적으로 간단한 방법을 찾고 있다면 다음과 같이 곱셈 연산자를 사용할 수 있습니다.

"Condition is "+("true"*$condition)+("false"*!$condition)
(12.34*$condition)+(56.78*!$condition)

어떤 것이 사실 일 때만 결과에 관심이 있다면 간단한 점수 시스템과 같이 허위 부분을 완전히 생략 할 수 있습니다 (또는 그 반대).

$isTall = $true
$isDark = $false
$isHandsome = $true

$score = (2*$isTall)+(4*$isDark)+(10*$isHandsome)
"Score = $score"
# or
# "Score = $((2*$isTall)+(4*$isDark)+(10*$isHandsome))"

부울 값은 곱셈의 주요 용어가 아니어야합니다. 즉 $ condition * "true"등이 작동하지 않습니다.


1

PowerShell 버전 7부터는 삼항 연산자가 PowerShell에 기본 제공됩니다.

1 -gt 2 ? "Yes" : "No"
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.