在Powershell函数中清除捕获的输出/返回值

时间:2014-07-03 08:31:41

标签: powershell

有没有办法清除函数内部的返回值,这样我可以保证返回值是我想要的?或者可能为函数关闭此行为?

在这个例子中,我希望返回值是一个包含(“Hello”,“World”)的ArrayList

function GetArray() 
{
    # $AutoOutputCapture = "Off" ?
    $myArray = New-Object System.Collections.ArrayList
    $myArray.Add("Hello")
    $myArray.Add("World")

    # Clear return value before returning exactly what I want?
    return $myArray
}

$x = GetArray
$x

但是,输出包含Add操作中捕获的值。

0
1
Hello
World

我发现Powershell的这个“功能”非常烦人,因为它只是通过调用另一个你不知道返回值的函数来打破你的函数非常容易。

更新

我知道有一些方法可以阻止输出被捕获(如下面的答案中所述),但这需要您知道函数实际返回一个值。如果您正在调用另一个Powershell函数,将来可能会有人更改此函数以返回一个值,这将破坏您的代码。

9 个答案:

答案 0 :(得分:7)

将输出管道输出到Out-Null,将输出重定向到$null,或者使用[void]为函数调用添加前缀:

$myArray.Add("Hello") | Out-Null

$myArray.Add("Hello") >$null

[void]$myArray.Add("Hello")

答案 1 :(得分:3)

我遇到了同样的问题。在PS中,函数将返回所有输出管道信息。函数中的| Out-Null其余代码变得棘手。 我通过传递return变量作为参考参数[ref]来解决这个问题。这始终如一。请查看下面的示例代码。 注意:一些语法对于避免错误很重要。例如参数必须在括号([ref]$result)

中传递
function DoSomethingWithFile( [ref]$result, [string]$file )
{
    # Other code writing to output
    # ....

    # Initialize result
    if (Test-Path $file){
        $result.value = $true
    } else {
        $result.value = $false
    }
}
$result = $null
DoSomethingWithFile ([ref]$result) "C:\test.txt" 

答案 2 :(得分:3)

使用来自user1654962的信息,以下是解决此PowerShell问题的方法。因为,如果有输出信息,PowerShell会将其作为数组返回,我决定确保函数输出始终是一个数组。然后调用行可以使用[-1]来获取数组的最后一个元素,我们将获得一致的返回值。

function DoSomething()
{
  # Code that could create output
  Write-Output "Random output that we don't need to return"
  Write-Output "More random output"

  # Create the return value. It can be a string, object, etc.
  $MyReturnString = "ImportantValue"

  # Other code

  # Make sure the return value is an array by preceding it with a comma
  return ,$MyReturnString
}

$CleanReturnValue = ( DoSomething() )[-1]

答案 3 :(得分:2)

我也有同样的挫败感!我有一个函数,其中一个变量应该计为$ <variablename> ++

除。我忘记了&#34; ++&#34;最后一次迭代。这导致变量的值被发送到输出缓冲区。找到它是非常加重和耗时的! MS应该至少提供在用户分配其所需返回值之前刷新输出缓冲区的能力。任何......我相信我有一个解决方法。

由于我在函数末尾指定了一个返回值,我所需的值将始终是输出缓冲区数组的最后一个条目。所以我改变了我调用函数的方式:

If (FunctionName (parameters)) {}

要:

If ((FunctionName (parameters))[-1]) {}

当我尝试捕获函数$ False返回时,我的特定情节让我感到困惑。由于我上面的拼写错误,我的IF语句因为输出中的垃圾而看起来是真的,即使我的上一个函数输出是&#34;返回$ False&#34;。由于拼写错误导致错误计算导致的问题,从函数分配的最后一个输出是$ False值。 所以将我的功能返回评估更改为:

If (!((FunctionName (parameters))[-1])) {#something went wrong!}

允许我只评估输出数组的最后一个元素。我希望这有助于其他人。

答案 4 :(得分:2)

只是想发布这个以防万一。我有多个函数我打电话。每个函数返回0或1.我用它来查看是否一切正常。

所以基本上......

function Funct1
{
   # Do some things
   return 1
}

$myResult += Funct1
$myResult += Funct2
$myResult += Funct3
if ($myResult -eq 3) { "All is good" }

一切顺利,直到我添加了一个具有一些Copy-Item和此类命令的函数。

长话短说,一两个小时我永远都不会回来,我发现了同样的问题。无论如何,在这样的网站的帮助下,我找到了最简洁的方法来确保你获得“回归”,而不是别的。

$myResult += Funct1 -split " " | Select-Object -Last 1
$myResult += Funct2 -split " " | Select-Object -Last 1
$myResult += Funct3 -split " " | Select-Object -Last 1

答案 5 :(得分:0)

为什么不使用Powershell Array对象而不是.Net arrayList?

您可以执行以下操作:

function GetArray() {
  # set $myArray as a powershell array   
  $myArray = @()
  $myArray+="Hello"
  $myArray+="World"
  # $myArray=@("Hello", "World") would work as well

  return $myArray
}

这将返回&#34; clean&#34;数组,正如所料。

如果你真的需要一个System.collections.ArrayList,你可以分两步完成:

  • 创建一个如上所述的powershell数组
  • 以这种方式转换.Net arrayList中的powershell数组:

    # Get the powershellArray 
    $x = getArray
    # Create a .Net ArrayList
    $myArrayList = New-Object System.Collections.ArrayList
    # Fill your arraylist with the powershell array
    $myArrayList.AddRange($x)
    

希望这有点帮助。

答案 6 :(得分:0)

我搜索了2018年写的答案,因为MS无疑使我们更容易做到这一点。

查看https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_return?view=powershell-6的评论

似乎将函数填充到类中可以有所帮助,但否则没有任何改变。

答案 7 :(得分:0)

这使我在使用更大的功能时遇到了麻烦。

可以将第一个答案“将管道输出到Out-Null”更进一步。我们将代码放入函数中,并将其嵌入到脚本块中,然后将其输出通过管道传递到Out-Null。

现在我们不需要遍历函数中的所有代码了……

vector<vector<int>> get_subsets1(vector<int> nums) {
    int full = 1 << nums.size();
    bitset<8 * sizeof(int)> set;
    vector<vector<int>> subsets;
    vector<int> temp;
    for (int i = 0; i < full; i++) {
        set = bitset<8 * sizeof(int)>(i);
        temp = vector<int>();
        for (int j = 0; j < nums.size(); j++)
            if (set[j])
                temp.push_back(nums[j]);
        subsets.push_back(temp);
    }
    return subsets;
}
int sum_vector(vector<int> vec) {
    return accumulate(vec.begin(), vec.end(), 0);
}

答案 8 :(得分:0)

将变量范围设置为脚本或全局。

function Get-Greeting {
    'Hello Everyone'
    $greeting = 'Hello World'
    'Ladies and Gentlemen'
    $script:greeting = $greeting
}

Get-Greeting
$greeting <== 'Hello World'