重定向到 Powershell 中的 $null 奇怪行为
Redirection to $null strange behavior in Powershell
有四种方法可以抑制输出:
- 重定向到
$null
变量
PS C:\> 1; $(2; return) > $null; 3
1
3
- 管道到
Out-Null
cmdlet
PS C:\> 1; $(2; return) | Out-Null; 3
1
2
- 转换为
[void]
类型
PS C:\> 1; [void]$(2; return); 3
1
2
- 赋值给
$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
命令。
行为解释
(来自 答案)
- in PS 1.0 和 2.0
> $null
操作在 before $()
表达式中执行并抑制其输出; return
命令不会从当前上下文中退出(被认为是 BUG),但会停止 $()
表达式执行
- 在 PS 3.0 和更新的
> $null
中执行 before $()
表达式并在所有情况下抑制其输出; return
命令完全退出当前上下文
| Out-Null
、[void]
、$null =
操作在$()
表达式后执行,如果没有则抑制其输出return
里面的命令; return
命令完全退出当前上下文
摘要
抑制命令输出的不同方法:
... > $null
重定向到 $null
变量
PS 1.0 和 2.0 中的错误。 PS 3.0+ 输出可能与其他方法不同
... | Out-Null
管道到 Out-Null
cmdlet
性能问题*
[void]...
转换为 [void]
类型
建议
$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
是最慢的,因为它 创建 一个复杂过程的管道;其他方法丢弃输出,不创建额外内容。
有四种方法可以抑制输出:
- 重定向到
$null
变量PS C:\> 1; $(2; return) > $null; 3 1 3
- 管道到
Out-Null
cmdletPS C:\> 1; $(2; return) | Out-Null; 3 1 2
- 转换为
[void]
类型PS C:\> 1; [void]$(2; return); 3 1 2
- 赋值给
$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
命令。
行为解释
(来自
- in PS 1.0 和 2.0
> $null
操作在 before$()
表达式中执行并抑制其输出;return
命令不会从当前上下文中退出(被认为是 BUG),但会停止$()
表达式执行 - 在 PS 3.0 和更新的
> $null
中执行 before$()
表达式并在所有情况下抑制其输出;return
命令完全退出当前上下文 | Out-Null
、[void]
、$null =
操作在$()
表达式后执行,如果没有则抑制其输出return
里面的命令;return
命令完全退出当前上下文
摘要
抑制命令输出的不同方法:
... > $null
重定向到$null
变量
PS 1.0 和 2.0 中的错误。 PS 3.0+ 输出可能与其他方法不同... | Out-Null
管道到Out-Null
cmdlet
性能问题*[void]...
转换为[void]
类型
建议$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
是最慢的,因为它 创建 一个复杂过程的管道;其他方法丢弃输出,不创建额外内容。