无论如何根据某些条件将管道数据发送到两个不同的路径,而不重新执行上游命令?这里的符号都是错的,但这是我想看到的......
PS> Get-SomeInterestingData `
| ?{ <condition> } `
| %{ <positive> } `
| %{ <negative> }
我可以使用嵌套的管道/表达式吗?
PS> Get-SomeInterestingData `
| %{
$_ | ?{ <condition> } | %{ <positive> } -or `
$_ | ?{ -not <condition> } | %{ <positive> }
}
如果您无法直接访问数据或数据生成功能,但是您是从管道接收的,该怎么办?比如说,作为脚本或函数param块的一部分,比如......
param(
[Parameter(ValueFromPipeline = $true)]
$InputObject,
)
答案 0 :(得分:5)
在PowerShell 4.0及更高版本中,您可以在Where()
模式下使用Split
扩展名方法:
$Even,$Odd = @(1..10).Where({$_ % 2 -eq 0},'Split')
输入集合将分为2个,满足过滤条件的项目和不满足过滤条件的项目。然后,您可以处理每个,而无需再次定义输入集合
答案 1 :(得分:4)
您可以使用Switch
cmdlet。
Switch(Get-SomeInterestingData){
{<positive>} {Do Stuff}
{<negative>} {Do Other Stuff}
}
答案 2 :(得分:2)
可悲的是,不是你希望的方式。
从技术上讲,这就是你所描述的;虽然不引人注意:
1..10 | %{
if ($_ % 2 -eq 0) { #even pipeline
$_ | write-host -ForegroundColor green #add whatever you want to happen on this pipeline instead of write-host
} else { #odd pipeline
$_ | write-host -ForegroundColor cyan #add whatever you want to happen on this pipeline instead of write-host
}
}
如果你想要更有趣的东西,这也会有用;虽然在许多情况下更令人困惑:
$PipelineIfTrue = {
[CmdletBinding()]
param ([Parameter(ValueFromPipeline = $true)][PSObject]$InputObject)
process {
$InputObject | write-host -ForegroundColor green
}
}
$PipelineIfFalse = {
[CmdletBinding()]
param ([Parameter(ValueFromPipeline = $true)][PSObject]$InputObject)
process {
$InputObject | write-host -ForegroundColor cyan
}
}
1..10 | %{$_ | &@($PipelineIfFalse, $PipelineIfTrue)[($_ % 2 -eq 0)]}
即。创建一些采用管道输入的脚本块;一个定义如果你的条件评估为真,一个假的。
我们将它们放在数组中并使用条件的结果来索引该数组;即如果为false(index = 0),我们返回PipelineIfFalse
脚本;如果为true(index = 1),我们返回PipelineIfTrue
。
&符号表示要执行此脚本,并且假设我们正在将当前值传递给此脚本,那么它将成为此匿名函数管道的参数。
<强>更新强>
因为我是一个虐待狂,所以我坚持下去。你可以这样做:
1..10 | Fork-Pipeline {$_ % 2 -eq 0} `
{ Write-Host -ForegroundColor green } `
{ Write-Host -ForegroundColor cyan }
或
1..10 | Fork-Pipeline `
-If {$_ % 2 -eq 0} `
-Then { Write-Host -ForegroundColor green } `
-Else { Write-Host -ForegroundColor cyan }
这是Cmdlet:
function Fork-Pipeline {
[CmdletBinding()]
param (
[Parameter(ValueFromPipeline = $true, Mandatory = $true)]
[PSObject]$InputObject
,
[Parameter(Mandatory = $true, Position=0)]
[Alias('If')]
[ScriptBlock]$Condition
,
[Parameter(Mandatory = $true, Position=1)]
[Alias('Then')]
[ScriptBlock]$PiplineIfTrue
,
[Parameter(Mandatory = $true, Position=2)]
[Alias('Else')]
[ScriptBlock]$PiplineIfFalse
)
begin {
#[string]$template = '[CmdletBinding()]param([Parameter(ValueFromPipeline=$true)]$InputObject)process{{$InputObject | {0}}}'
[string]$template = '$_ | {0}' #much simpler version of the above
$FunctionIfTrue = [scriptblock]::Create($template -f $PiplineIfTrue.ToString())
$FunctionIfFalse = [scriptblock]::Create($template -f $PiplineIfFalse.ToString())
}
process {
if (&$Condition) {
$InputObject | &$FunctionIfTrue
} else {
$InputObject | &$FunctionIfFalse
}
}
}
我不推荐这种做法;它不会表现得非常好,并且很可能会混淆那些习惯于处理普通PS管道的人。非常适合学术乐趣。