bestsource

PowerShell 함수에서 하나의 값만 반환하는 방법은 무엇입니까?

bestsource 2023. 8. 2. 09:16
반응형

PowerShell 함수에서 하나의 값만 반환하는 방법은 무엇입니까?

스택 오버플로 질문을 통해 PowerShell 반환 시맨틱이 C# 반환 시맨틱과 다르다는 것을 알게 되었습니다.앞서 언급한 질문의 인용:

PowerShell은 적어도 더 전통적인 프로그래밍 관점에서 볼 때 정말 이상한 반환 의미를 가지고 있습니다.머리를 감아야 할 두 가지 주요 아이디어가 있습니다.모든 출력이 캡처되어 반환됩니다.return 키워드는 논리적 종료 지점을 나타냅니다.

다음 예를 살펴보겠습니다.

function Calculate
{
   echo "Calculate"
   return 11
}

$result = Calculate

메아리친다면,$result당신은 무언가가 옳지 않다는 것을 깨닫게 될 것입니다.다음과 같이 예상할 수 있습니다.

11

하지만 현실은, 실제로 보는 것과 다릅니다.

Calculate
11

따라서 의도된 반환 값만 반환하는 대신 어레이를 반환합니다.

에코문을 제거하고 반환값을 오염시키지 않을 수 있지만, 만약 당신이 당신의 기능에서 다른 함수를 호출한다면, 그것은 무엇인가를 반향시킵니다. 그러면 당신은 다시 곤경에 처하게 됩니다.

하나만 반환하는 PowerShell 함수를 작성하려면 어떻게 해야 합니까?내장된 PowerShell 기능이 하나의 값만 반환하는 경우 이를 수행할 수 없는 이유는 무엇입니까?

현재 사용하고 있는 해결 방법은 다음과 같습니다.

function Calculate
{
   # Every function that returns has to echo something
   echo ""
   return 11
}

# The return values is the last value from the returning array
$result = (Calculate)[-1]

모든 항목을 null로 할당한 다음 원하는 변수만 반환할 수도 있습니다.

Function TestReturn {

    $Null = @(
        Write-Output "Hi there!"
        1 + 1
        $host
        $ReturnVar = 5
    )
    return $ReturnVar
}

이미 제공된 몇 가지 답변은 귀하가 지적한 것처럼 출력을 "오염"할 수 있는 다른 cmdlet을 설명하지 않기 때문에 귀하의 질문에 완전히 대답하지 못합니다.@Laezzylion의 대답은 기본적으로 옳지만 저는 더 자세히 설명할 수 있다고 믿습니다.

모든 함수를 강제로 배열을 반환한 다음 마지막 요소를 사용하는 현재 해결 방법은 그다지 강력한 솔루션이 아닙니다.(사실, 저는 그것을 둔덕이라고 부르는 것이 안전하다고 생각합니다. :-) 정확한 접근법과 질문에 대한 직접적인 대답은 명확합니다.언뜻 보기에는 문신처럼 들리지만,

Question: How do you ensure a function returns only one thing?
Answer: By ensuring that it returns only one thing.

설명하겠습니다.PowerShell에는 (A) 데이터를 반환하는 기능과 (B) 데이터를 반환하지 않고 진행률 또는 진단 메시지를 보고할 수 있는 기능의 두 가지가 있습니다.문제는 앞서 살펴본 바와 같이 두 가지를 혼합하려고 할 때 발생합니다.그리고 이러한 일은 부주의로 인해 쉽게 발생할 수 있습니다.따라서 함수 작성자는 함수 내의 각 함수/cmdlet 호출을 이해할 책임이 있습니다. 구체적으로 함수가 반환하는 것이 무엇인지, 실제 반환 값인지, 아니면 단순히 진단 출력인지 등입니다.당신은 A형 함수의 출력을 기대하고 있지만, B형 함수에 주의해야 합니다.무언가를 반환하는 사람은 변수에 할당하거나 파이프라인에 공급하거나... 제거해야 합니다. (Out-Null로 파이프를 연결하거나, void로 캐스팅하거나, $null로 리디렉션하거나, $null로 할당하는 등 여러 가지 방법이 있습니다.)이러한 각 맛의 성능을 평가하는 Jason Archer의 Stack Overflow 게시물을 참조하십시오. 이 게시물은 Out-Null을 피하는 것을 참조하십시오.

예, 이 접근 방식은 더 많은 노력이 필요하지만 그렇게 함으로써 더 강력한 솔루션을 얻을 수 있습니다.바로 이 문제에 대해 조금 더 자세히 설명하려면 이러한 A/B 기능 등을 참조하십시오. 최근 Simple-Talk.com 에 게시된 PowerShell Pitles의 여러 가지에 대한 질문 1을 참조하십시오.

사용 안 함echo정보를 작성하려면, 사용Write-Host,Write-Verbose또는Write-Debug전언에 따라

Echo의 별칭입니다.Write-Output파이프라인을 통해 객체로 전송됩니다.Write-Host/Verbose/Debug그러나 콘솔에서만 실행됩니다.

PS P:\> alias echo

CommandType Name                 ModuleName
----------- ----                 ----------
Alias       echo -> Write-Output               

샘플:

function test {
    Write-Host calc
    return 11
}

$t = test
"Objects returned: $($t.count)"
$t

#Output
calc
Objects returned: 1
11

또한 함수의 마지막 줄에 값을 반환하는 경우에는 다음을 사용할 필요가 없습니다.return개체/값을 직접 작성하는 것만으로도 충분합니다.

function test {
    Write-Host calc
    11
}

다른 점은return 11함수 중간에 사용하면 줄을 건너뜁니다.

function test {
    return 11
    12
}

test

#Output
11

언급할 가치가 있는 항목:

함수 내의 관리되지 않는 명령 출력은 반환 값으로 종료됩니다.

XML 컨텐츠를 관리하는 기능으로 인해 다음과 같은 문제가 발생하곤 합니다.

Function Add-Node(NodeName){
    $NewXmlNode = $Xml.createElement("Item")
    $Xml.Items.appendChild($NewXmlNode) | out-null
}

Out-Null을 제거하면 함수의 반환은 노드 기본 속성이 됩니다...(appendChild 명령의 종료 코드를 관리할 수도 있습니다...동기에 따라 다릅니다) :)

@Michael Sorens의 답변은 유용하지만 다소 부담스러운 디자인 전략을 제안합니다.진행 상황이나 진단 메시지를 보고하는 기능에서 데이터 처리 기능을 분리하고 싶지 않습니다.그의 블로그 게시물을 읽으면서, 저는 OP의 질문에 대한 덜 진부한 해결책을 발견했습니다.블로그 게시물의 핵심 문장은 다음과 같습니다.

PowerShell 함수는 캡처되지 않은 모든 출력을 반환합니다.

그러면 우리가 우리의 산출물을 포착하면 어떨까요?

function Calculate
{
   $junkOutput = echo "Calculate"
   return 11
}

$result = Calculate

지금이다$result의도한 대로 11개만 포함됩니다.

대체할 수 있습니다.echo(쓰기-출력의 별칭)(쓰기-호스트 포함):

PS> function test{ Write-Host "foo";"bar"} 
PS> $a = test                                    
test                                          
PS >$a                                         
bar

echo는 개체를 다음 명령으로 보내는 쓰기 출력의 별칭입니다.

쓰기 호스트를 사용하면 다음과 같은 이점이 있습니다.

PS:> function Calculate
>> {
>>    # Every function that returns has to echo something
>>    Write-Host "test"
>>    return 11
>> }
>>
PS:> $A = Calculate
test
PS:> $A
11

매개 변수를 허용하는 함수를 호출할 때 괄호 사용이 중요한 것 같습니다.이 예제는 SQL Server의 데이터 테이블을 채우고 첫 번째 행, 네 번째 열에서 [int]를 반환합니다.[int]$tt1 변수에 할당된 실제 함수 호출 주위의 괄호를 기록합니다.

    function InvokeSQL-GetOneCount { param( [string]$cn, [string]$prj )
        $sql = "SELECT * FROM [dbo].[dummytable] WHERE ProjectNumber = '$prj' ORDER BY FormID, PartID;"

        $handler = [System.Data.SqlClient.SqlInfoMessageEventHandler] { param($sender, $event) Handle-Message -message $event.Message -fcolor "yellow" -bcolor "black"; };
        $conn = new-Object System.Data.SqlClient.SqlConnection($cn)
        $conn.add_InfoMessage($handler); 
        $conn.FireInfoMessageEventOnUserErrors = $true;

        $cmd = New-Object System.Data.SqlClient.SqlCommand;
        $cmd.Connection = $conn;
        $cmd.CommandType = [System.Data.CommandType]::Text;
        $cmd.CommandText = $sql;
        $cmd.CommandTimeout = 0;

        $sa = New-Object System.Data.SqlClient.SqlDataAdapter($cmd);
        $dt = New-Object System.Data.DataTable("AllCounts");
        $sa.Fill($dt) | Out-Null;

        [int]$rval = $dt.Rows[0][3];

        $conn.Close();
        return $rval;
    }
    clear-host;
    [int]$tt1 = (InvokeSQL-GetOneCount -cn "Server=[your server];DataBase=[your catalog];Integrated Security=SSPI" -prj "MS1904");
    write-host $tt1;

결국 다음을 사용하여 하나의 값만 반환되도록 했습니다.

  • write-host '일부 콘솔 메시지'
  • invoke-some-detail arg1 arg2 | 쓰기 호스트
  • functionCall arg1 arg2 | out-null # 출력 억제
  • 원하는 값 반환

PowerShell은 파이프 작업을 어색하게 수행합니다.반환 값 문제를 해결하고 실제 데이터에 대한 파이프라인을 저장하려면 함수를 기준으로 값, 즉 배열로 전달합니다.반환할 값으로 배열을 로드할 수 있습니다.다음은 간단한 예입니다.

# tp.ps1
#   test passed parameters
#   show that arrays are passed by reference, and can be used to provide
#   return values outside the pipeline
function doprint
{
    process { write-output "value now: $psitem" }
}

function recurse($thing,     $rtx)
{
    $thing++
    if($thing -lt 20) {
        if($thing -eq 15) { $rtx[0] = $thing }
        write-output $thing | doprint
        recurse $thing     $rtx
    }
}

j=0
$rtv=@(4)
recurse $j     $rtv
write-output $rtv[0]

나는 파워셸이 얼마나 큰지 놀랐습니다.return왜냐하면 저는 값을 반환하는 함수를 쓸 필요가 없었기 때문입니다.변수 자체가 아니라 함수의 모든 출력 스트림을 반환합니다.출력을 전달하지 않으려면 Out-Null을 사용해야 합니다.예를 들어 다음과 같습니다.

function Calculate
{
   . {
       echo "Calculate"
       $result = 11
       return
   } | Out-Null
   
   return $result
}

$result = Calculate

결과는 다음과 같습니다.

11

https://riptutorial.com/powershell/example/27037/how-to-work-with-functions-returns 에 대한 크레딧

언급URL : https://stackoverflow.com/questions/29556437/how-to-return-one-and-only-one-value-from-a-powershell-function

반응형