有没有简洁的方法将一些现有变量作为参数传递给Powershell函数?

时间:2013-12-20 16:21:53

标签: powershell

我似乎经常发现自己处于一种情况,我设置了一堆变量,并且我想将它们传递给一个函数(例如,将参数传递给另一个函数而不进行修改)。目前我最终做了这样的事情:

Get-RelatedThing -CompanyTag $CompanyTag -ProjectTag $ProjectTag -EnvName $EnvName

这看起来很冗长,而且不易读取。我可以使用位置参数,但这会牺牲清晰度和兼容性。预先创建一个数组并使用splatting只会产生垂直杂波而不是水平(除非在不寻常的情况下,我可以做一些像Get-RelatedThing @PSBoundParameters,但这有陷阱)。

我真正喜欢的是能够做到这样的事情:

Get-RelatedThing @(Get-Variable CompanyTag,ProjectTag,EnvName)

但是Get-Variable返回一个Object [],而splatting运算符只能解析一个名为params(或一个位置参数数组)的哈希表。我stole是解决这个问题的函数:

function Get-VariablesAsHashtable {

[CmdletBinding()]
param
(
    [Parameter(Position=0)]
    [string[]] $Name
)

$ObjectArray = Get-Variable -Name @($Name)

$Hashtable = @{}
$ObjectArray | Foreach { $Hashtable[$_.Name] = $_.Value }

return $Hashtable

}

在“提前”运行时有效:

# works
$calculatedVars = (Get-VariablesAsHashtable ProjectTag,EnvName,ComponentTag);
(Get-RelatedThing @calculatedVars);

但不是在“内联”运行时:

# fails
(Get-RelatedThing @(Get-VariablesAsHashtable ProjectTag,EnvName,ComponentTag));

Get-InitialThing : Cannot process argument transformation on parameter 'ProjectTag'. Cannot convert value to type System.String.

我是否遗漏了可以修复此方法的内容?或者有更好的方法吗?

2 个答案:

答案 0 :(得分:1)

看看这是否有效:

Get-RelatedThing @($(Get-Variable CompanyTag,ProjectTag,EnvName))

你可以用不同的功能实际上简化一些。这显示了splatting哈希表的效果:

$Params = @{
CompanyTag = 'Company1'
ProjectTag = 'Project1'
EnvName    = 'Env1'
}

[Scriptblock]::Create("$(&{$args}@Params)")

-EnvName: Env1 -CompanyTag: Company1 -ProjectTag: Project1

修改原始功能以重现:

function Get-VariablesAsParameters {

[CmdletBinding()]
param
(
    [Parameter(Position=0)]
    [string[]] $Name
)

$ObjectArray = Get-Variable -Name @($Name)
[string]($ObjectArray | Foreach { '-{0}: {1}' -f $_.Name,$_.Value})

}

function Get-RelatedThing {$args}

Get-RelatedThing $(Get-VariablesAsParameters CompanyTag,ProjectTag,EnvName)
-CompanyTag: Company1 -ProjectTag: Project1 -EnvName: Env1

答案 1 :(得分:1)

实际上,你认为splatting只适用于hashtables是错误的。它也适用于数组,但它使用数组的每个元素作为被调用命令的位置参数。如果您确定所有值都在那里,那么您可以简单地绘制数组:

function Test-Binding {
param (
    $Foo,
    $Bar
)
    "Foo: $Foo"
    "Bar: $Bar"
}

$Foo = 'first value'
$Bar = 'other value'

$Splat = @(Get-Variable -ValueOnly Foo, Bar)

Test-Binding @Splat

你尝试过的内联语法失败的原因非常简单:在这种情况下,你不会出现问题。你在这一行中真正做了什么:

(Get-RelatedThing @(Get-VariablesAsHashtable ProjectTag,EnvName,ComponentTag));

...正在传递单个参数,你强制成一个数组(在这种情况下是@()代表什么),单个哈希表的数组(你的函数产生的数组)。没有办法splat hashtable你正在构建“ad hoc”。您需要先构建它,存储在变量x中,然后使用@x文字而不是通常的$x将此变量作为“splat”传递。

我听说过填补这个空白的建议(语法如:command @@{ foo = 'bar'})但是在此之前,您必须先构建哈希表/数组,然后使用变量名称和@进行展开前缀。