【发布时间】:2016-10-09 03:08:16
【问题描述】:
(Powershell 5)
我有以下合并功能:
(更新:删除了 process 块中的“优化”continue 调用。)
function Find-Defined {
begin {
$ans = $NULL;
$Test = { $_ -ne $NULL };
}
process {
if ( $ans -eq $NULL ) {
$ans = $_ |? $Test | Select -First 1;
}
}
end {
if ( $ans -ne $NULL ) {
return $ans;
}
else {
$Args `
|% { if ( $_ -is [Array] ) { $_ |% { $_ } } else { $_ } } `
|? $Test `
| Select -First 1 `
| Write-Output `
;
}
}
}
这对我来说非常有效,在如下命令行中:
$NULL, $NULL, 'Legit', 1, 4 | Find-Defined;
$NULL, $NULL | Find-Defined $NULL, @( $NULL, 'Value' ), 3;
$NULL, $NULL | Find-Defined $NULL $NULL 3 4;
您可能会注意到我将决策逻辑封装在 ScriptBlock 变量中。这是因为我想参数化它,我开始尝试这个。
[CmdletBinding()]param( [ScriptBlock] $Test = { $_ -ne $NULL } );
但是,在我添加 CmdletBinding 的那一刻,我开始出错。绑定想尝试将参数部分中的所有内容都转换为ScriptBlock,所以我添加了
[CmdletBinding(PositionalBinding=$False)]
然后它抱怨无法绑定未绑定的参数,所以我补充说:
param( [parameter(Mandatory=$False,Position=0,ValueFromRemainingArguments=$True)][Object[]] $Arguments ...
之后我所做的一切都添加了一个新错误。如果我删除了$Test 参数,只是将其本地化以查看我能做什么,然后我开始收到我在开发第一代时遇到的错误:
The input object cannot be bound to any parameters for the command either
because the command does not take pipeline input or the input and its
properties do not match any of the parameters that take pipeline input.
...即使我有一个process 块。
最后干脆去掉param语句,把它放回我喜欢的灵活功能。
我仍然希望扩展此功能以接受 ScriptBlock 测试和 unbound 参数(以及像 -Verbose 这样的通用参数,如果可能的话)。这样我也可以有一个用于 string 合并的通用算法:
$Test = { -not [string]::IsNullOrEmpty( [string]$_ ) };
$NULL,$NULL,'','' | Find-Defined -Test $Test $NULL,'','This should be it' 'Not seen'
我错过了什么吗?
【问题讨论】:
-
顺便说一句,
continue是循环控制指令。很可能,当您将函数放入脚本时,它的行为会出乎您的意料。 -
@PetSerAl:你是对的。在与原始文件混在一起时,我添加了一些其他步骤——就像没有在
begin块中指定ScriptBlock一样。我会改回来的。
标签: powershell parameter-passing