如何从PowerShell函数返回一个且只有一个值?

bol*_*oli 33 powershell

我从这个StackOverflow问题中了解到,$result返回语义是不同的,让我们从$result返回语义中说出来.引用上述问题:

PowerShell具有非常古怪的返回语义 - 至少从更传统的编程角度来看是这样.有两个主要想法可以解决:所有输出都被捕获并返回.return关键字实际上只是表示逻辑退出点.

我们来看看这个例子:

function Calculate
{
   echo "Calculate"
   return 11
}

$result = Calculate
Run Code Online (Sandbox Code Playgroud)

如果你回声,$result你会发现事情是不对的.你期望这个:

11
Run Code Online (Sandbox Code Playgroud)

但实际情况,你实际看到的,是不同的:

Calculate
11
Run Code Online (Sandbox Code Playgroud)

因此,您实际上只返回一个数组,而不是仅返回预期的返回值.

你可以摆脱echo语句而不是污染返回值,但是如果你从你的函数中调用另一个函数,它回应了某些东西,那么你又会遇到麻烦.

我的问题是,我怎么能写一个$result只返回一件事的函数.如果内置$result函数只返回一个值,为什么我不能这样做呢?

我现在正在使用的解决方法,我很想摆脱:

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]
Run Code Online (Sandbox Code Playgroud)

小智 19

您也可以将所有内容分配给null,然后只返回您想要的变量:

Function TestReturn {

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


Mic*_*ens 8

已经给出的几个答案并没有完全回答你的问题,因为他们没有考虑你可能会调用的其他 cmdlet - 正如你所指出的那样 - 可能会"污染"你的输出.来自@Laezylion的答案基本上是正确的,但我相信还有进一步的阐述.

很明显,您了解当前的解决方法 - 强制每个函数返回一个数组然后采用最后一个元素 - 并不是一个非常强大的解决方案.(事实上​​,我认为称之为kludge是安全的.:-)正确的方法 - 并直接回答你的问题 - 很明显......虽然乍一看它听起来像是重言式:

Question: How do you ensure a function returns only one thing?
Answer: By ensuring that it returns only one thing.
Run Code Online (Sandbox Code Playgroud)

让我来澄清一下.PowerShell中实际上有两种函数/ cmdlet:(A)返回数据的函数和(B)那些不返回数据但可以报告进度或诊断消息的函数/ cmdlet.正如您所看到的,当您尝试将两者混合时出现问题.这可能很容易在无意中发生.因此,作为函数作者,您有责任理解函数中的每个函数/ cmdlet调用:具体而言,它是否返回任何内容,无论是真正的返回值还是仅仅是诊断输出?您期望从A类函数输出,但您需要警惕任何类型B函数.对于任何确实返回某个内容的人,您必须将其分配给变量,将其提供给管道,或者......让它消失.(有几种方法可以消除它:将它传递给Out-Null,将其转换为void,将其重定向到$ null,或将其分配给$ null.请参阅Jason Archer的Stack Overflow帖子,评估每个这些的性能味道,暗示你回避Out-Null.)

是的,这种方法需要付出更多努力,但是通过这样做可以获得更强大的解决方案.有关这个问题的更多讨论,这些A/B功能等,请参阅最近在Simple-Talk.com上发布的关于Plehell of PowerShell陷阱的问题1 .

  • `+ 1`用于真正有用的信息.`-1`没有提供可维护的解决方案,但是暗示现状是可以接受的:*"因此,作为函数作者,您有责任理解函数中的每个函数/ cmdlet调用:具体来说,它是否返回什么,无论是真正的回报价值还是只是诊断输出?"* - 认真的人?这有多疯狂?我必须知道我打电话*是否*可能*在某些时候输出诊断信息?Pfff. (2认同)

Fro*_* F. 6

不要用echo写信息,使用Write-Host,Write-VerboseWrite-Debug取决于消息.

Echo是一个别名Write-Output,它将通过管道将其作为Object发送.Write-Host/Verbose/Debug但只是控制台消息.

PS P:\> alias echo

CommandType Name                 ModuleName
----------- ----                 ----------
Alias       echo -> Write-Output               
Run Code Online (Sandbox Code Playgroud)

样品:

function test {
    Write-Host calc
    return 11
}

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

#Output
calc
Objects returned: 1
11
Run Code Online (Sandbox Code Playgroud)

此外,如果在函数的最后一行返回值,则无需使用return.单独编写Object/value就足够了.

function test {
    Write-Host calc
    11
}
Run Code Online (Sandbox Code Playgroud)

不同之处在于return 11,在函数中间使用它之后会跳过这些行.

function test {
    return 11
    12
}

test

#Output
11
Run Code Online (Sandbox Code Playgroud)


小智 6

值得一提的是:函数中的任何非托管命令输出都将以返回值结束.

我用管理XML内容的函数来解决这个问题:

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

如果删除Out-Null,函数的返回将是Node基本属性...(您还可以管理appendChild命令的退出代码...取决于动机):)