PowerShell의 return은 변수에 저장하는 것이 오류 처리에 안전하다는 이야기입니다.

이른바 early-return 이라는 것을 PowerShell로 하려고 했을 때에 빠졌기 때문에 메모.

환경



Name                           Value
----                           -----
PSVersion                      7.0.3
PSEdition                      Core
GitCommitId                    7.0.3
OS                             Microsoft Windows 10.0.18362
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0


경위



PowerShell에서 제목이 중복된 csv를 ConvertFrom-Csv하려고 하면 오류가 발생합니다.
PS> cat .\target.csv
AA,AA,BB
10,20,30
40,50,60

PS> cat target.csv | ConvertFrom-Csv
ConvertFrom-Csv: The member "AA" is already present.

그러나 다음 함수를 실행해 보면 ......
function func1 {
    if($true){
        return (cat target.csv | ConvertFrom-Csv)
    }
    Write-Output "ここは出力されてほしくない"
}


 !?

아무래도 return 에 실패하면 return 처리가 무시되어 이후의 행에 처리가 옮겨지고 있는 모습. -ErrorAction 파라미터에 Stop 를 지정해도 관계없는 것 같습니다.
function func2 {
    if($true){
        return (cat target.csv | ConvertFrom-Csv -ErrorAction Stop)
    }
    Write-Output "ここは出力されてほしくない"
}



명시 적으로 Write-Output 그러면 그 행에서 오류로 처리가 중지되는 것 같습니다. 그러나 기술을 간략화하기 위한 early-return 로 문자수가 늘어나는 것은 본말 전도…
function func3 {
    if($true){
        cat target.csv | ConvertFrom-Csv | Write-Output
        return
    }
    Write-Output "ここは出力されてほしくない"
}



변수에 저장하도록 하면 제대로 에러 취급이 되었습니다. 조금 설명이 줄어 듭니다.
function func4 {
    if($true){
        $ret = (cat target.csv | ConvertFrom-Csv)
        return $ret
    }
    Write-Output "ここは出力されてほしくない"
}



변수에 저장하면 좋다는 것을 알았으므로, return $() 로 하는 것이 가장 간단하네요.
function func5 {
    if($true){
        return $(cat target.csv | ConvertFrom-Csv)
    }
    Write-Output "ここは出力されてほしくない"
}



결국, $ 하나 추가하는 것만으로 좋았던 것이었습니다(하지만 Qiita의 신택스 하이라이트적으로는 에러…?).

결론



return 내용은 변수에 저장해야합니다.

return 처리 자체가 없었던 것이 되는 것은 상당한 함정이군요. 문서  에도 () 는 그 안을 모두 평가하고 나서 이후에 파이프한다고 하는 이상의 설명이 없기 때문에 당황했습니다. 심장에 나쁘다…

좋은 웹페이지 즐겨찾기