重定向到 Powershell 中的 $null 奇怪行为

Redirection to $null strange behavior in Powershell

有四种方法可以抑制输出:

  1. 重定向到 $null 变量
    PS C:\> 1; $(2; return) > $null; 3
    1
    3
    
  2. 管道到 Out-Null cmdlet
    PS C:\> 1; $(2; return) | Out-Null; 3
    1
    2
    
  3. 转换为 [void] 类型
    PS C:\> 1; [void]$(2; return); 3
    1
    2
    
  4. 赋值给$null变量
    PS C:\> 1; $null = $(2; return); 3
    1
    2
    

所有四种情况都应该是等价的。

为什么重定向到 $null 的行为不同?我遇到错误了吗?

另一个例子

此示例显示 > $null 命令在 PS 2.0:

中的意外行为
PS C:\> 1; $(Write-Output 2; Write-Host 3; return; Write-Host 4) > $null; 5
1
3
5

return 命令就好像它从某个嵌套上下文中退出一样(虽然没有创建它的命令),停止 $() 表达式执行然后继续执行(当它不应该) 在当前上下文中到 Write-Output 5 命令。

行为解释

(来自 答案)

摘要

抑制命令输出的不同方法:

  1. ... > $null 重定向到 $null 变量
    PS 1.0 和 2.0 中的错误。 PS 3.0+ 输出可能与其他方法不同
  2. ... | Out-Null 管道到 Out-Null cmdlet
    性能问题*
  3. [void]... 转换为 [void] 类型
    建议
  4. $null = ... 赋值给 $null 变量
    建议
  • 2实际上执行为Write-Output 2

  • $() 在同一上下文中执行包含的代码,它不会创建新的上下文。

    创建新上下文的东西是像 & { ... }1..2 | ForEach { ... }
    这样的脚本块 ({ ... }).Invoke()select @{N='calculated property'; E={$_.foo}} 和函数。

  • 因此,$( return ) 从当前上下文中退出,因此 之后不应评估任何内容(换句话说,PowerShell 1.0 和 2.0 有一个错误).

重定向输出流:

1; $(2; return) > $null; 3

整个$()表达式的输出流本身被>$null抑制,这是在计算表达式之前决定的,return在[=23]之前从当前上下文中退出=] 有机会。

PS 3(及更新版本)仅正确打印 1:

1

PS 1 和 2 错误地打印了两个数字,这确实是一个错误:

1
3

正在处理输出流:

1; [void]$(2; return); 3
1; $null = $(2; return); 3
1; $(2; return) | Out-Null; 3

1
2

2 被推送到这里的输出流,然后 return 在后续操作发生(转换、分配、流水线)之前退出当前上下文。

至于性能差异,请参阅 this answer| Out-Null 是最慢的,因为它 创建 一个复杂过程的管道;其他方法丢弃输出,不创建额外内容。