PS7.1 - 如何将管道链接与自定义函数一起使用?
PS7.1 - How do you use pipeline chaining with custom functions?
根据文档,PS 7 引入了管道链运算符,例如 ||
和 &&
。
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_pipeline_chain_operators?view=powershell-7
而且您应该能够执行 C# 风格的短路操作,例如:
Write-Error 'Bad' && Write-Output 'Second'
以上示例有效。并且文档说管道链接运算符使用两个字段(不确定它是如何工作的):$?
和 $LASTEXITCODE
如何将这些应用到我自己的函数中?
例如:
function yes() {
echo 'called yes'
return $True
}
function no() {
echo 'called no'
return $False
}
我觉得我应该能够运行以下no && yes
并看到以下输出
called no
False
但我看到了
called no
False
called yes
True
那么我该如何开发可以使用流水线链接和短路的函数呢?
编辑:我现在能想出的唯一方法是构造一个自定义函数来短路 &&
是使它成为 throw
,但这似乎不太有用一般情况。
&&
和 ||
仅对命令的 成功状态 进行操作,如automatic $?
variable(如您所说)- 与命令 输出的内容无关 (returns).
函数和脚本将 $?
报告为 $true
,除非采取明确的操作;也就是说,即使在脚本/函数中使用的命令失败,当脚本/函数退出时,$?
仍然是 $true
。
不幸的是,从 PowerShell 7.0 开始,函数 无法直接将 $?
设置为 $false
,尽管计划是添加这样的功能 - 请参阅 this GitHub isssue。
在脚本中,使用带有非零退出代码的exit
是有效的,但是(这会导致$LASTEXITCODE
以反映退出代码,如果退出代码为非零,PowerShell 引擎将 $?
设置为 $false
- 这也是您调用 外部程序时的工作方式 ).
目前,函数只有以下次优解决方法;它不是最理想的,因为它 总是发出一条错误消息 :
function no {
# Make the function an advanced one, so that $PSCmdlet.WriteError()
# can be called.
[CmdletBinding()]
param()
# Call $PSCmdlet.WriteError() with a dummy error, which
# sets $? to $false in the caller's scope.
# By default, this dummy error prints and is recorded in the $Error
# collection; you can use -ErrorAction Ignore on invocation to suppress
# that.
$PSCmdlet.WriteError(
[System.Management.Automation.ErrorRecord]::new(
[exception]::new(), # the underlying exception
'dummy', # the error ID
'NotSpecified', # the error category
$null) # the object the error relates to
)
}
函数 no
现在将 $?
设置为 false,从而触发 ||
分支; -EA Ignore
(-ErrorAction Ignore
) 用于消除虚拟错误。
PS> no -EA Ignore || 'no!'
no!
根据文档,PS 7 引入了管道链运算符,例如 ||
和 &&
。
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_pipeline_chain_operators?view=powershell-7
而且您应该能够执行 C# 风格的短路操作,例如:
Write-Error 'Bad' && Write-Output 'Second'
以上示例有效。并且文档说管道链接运算符使用两个字段(不确定它是如何工作的):$?
和 $LASTEXITCODE
如何将这些应用到我自己的函数中?
例如:
function yes() {
echo 'called yes'
return $True
}
function no() {
echo 'called no'
return $False
}
我觉得我应该能够运行以下no && yes
并看到以下输出
called no
False
但我看到了
called no
False
called yes
True
那么我该如何开发可以使用流水线链接和短路的函数呢?
编辑:我现在能想出的唯一方法是构造一个自定义函数来短路 &&
是使它成为 throw
,但这似乎不太有用一般情况。
&&
和 ||
仅对命令的 成功状态 进行操作,如automatic $?
variable(如您所说)- 与命令 输出的内容无关 (returns).
函数和脚本将 $?
报告为 $true
,除非采取明确的操作;也就是说,即使在脚本/函数中使用的命令失败,当脚本/函数退出时,$?
仍然是 $true
。
不幸的是,从 PowerShell 7.0 开始,函数 无法直接将 $?
设置为 $false
,尽管计划是添加这样的功能 - 请参阅 this GitHub isssue。
在脚本中,使用带有非零退出代码的exit
是有效的,但是(这会导致$LASTEXITCODE
以反映退出代码,如果退出代码为非零,PowerShell 引擎将 $?
设置为 $false
- 这也是您调用 外部程序时的工作方式 ).
目前,函数只有以下次优解决方法;它不是最理想的,因为它 总是发出一条错误消息 :
function no {
# Make the function an advanced one, so that $PSCmdlet.WriteError()
# can be called.
[CmdletBinding()]
param()
# Call $PSCmdlet.WriteError() with a dummy error, which
# sets $? to $false in the caller's scope.
# By default, this dummy error prints and is recorded in the $Error
# collection; you can use -ErrorAction Ignore on invocation to suppress
# that.
$PSCmdlet.WriteError(
[System.Management.Automation.ErrorRecord]::new(
[exception]::new(), # the underlying exception
'dummy', # the error ID
'NotSpecified', # the error category
$null) # the object the error relates to
)
}
函数 no
现在将 $?
设置为 false,从而触发 ||
分支; -EA Ignore
(-ErrorAction Ignore
) 用于消除虚拟错误。
PS> no -EA Ignore || 'no!'
no!