我有一个返回哈希表的命令。像这样,例如:
function Get-TestArgs() { return @{a=1;b=2;c=3} }
我想将其返回值用作我的其他函数的参数:
function Test($a, $b, $c) {
Write-Host 'A' $a
Write-Host 'B' $b
Write-Host 'C' $c
}
使用PowerShell的splatting功能可以实现这一点:
$testargs = @{a=1;b=2;c=3}
Test @testargs
问题是我不想将哈希值分配给中间变量。
我想到的是这些方面的东西:
Test (some splat syntax)(Get-TestArgs)
显然,这不起作用,因为它只是创建一个包含哈希的数组并传递:
Test @(Get-TestArgs)
有没有办法实现这个目标?
我正在编写将手动执行的指令。这些说明将调用脚本,但在调用之间仍有一些手动干预。因此,我希望最大限度地减少命令,以减少出现问题的风险,例如变量是其他命令或输入错误。
答案 0 :(得分:6)
我认为没有变量就可以使用splatting。但是,实现您正在寻找的东西的解决方法很少。
编写一个包装函数,该函数将采用哈希表并调用' real'功能。如果您想直接调用此函数,而不使用Get-TestArgs
,则可以使用TestInner
。
function Get-TestArgs() { return @{a=1;b=2;c=3} }
function TestInner ($a, $b, $c)
{
write-host "a=" $a
write-host "b=" $b
write-host "c=" $c
}
function Test ($hash) {
return TestInner @hash
}
Test (Get-TestArgs)
TestInner 1 2 3
设计你的函数,使每个函数都将哈希表作为唯一参数 - 它是1的简化版本。它看起来有点难看 - 你无法确定Test
所需的参数看着它的宣言。
function Test ($hash)
{
write-host "a=" $hash.a
write-host "b=" $hash.b
write-host "c=" $hash.c
}
Test (Get-TestArgs)
使用2.中的方法,但为函数参数创建一个新类型,以便更加安全":
add-type -TypeDefinition @"
public class TestArg {
public int a = 0;
public int b = 0;
public int c = 0;
}
"@
function Get-TestArgs() { return new-object -type "TestArg" -Property @{a=1;b=2;c=3} }
function Test ([TestArg] $o)
{
write-host "a=" $o.a
write-host "b=" $o.b
write-host "c=" $o.c
}
Test (Get-TestArgs)
利用参数集和管道。这类似于编写包装器,但目标函数也是包装器 - 根据参数集,它将正常执行或使用splatting再次调用自身,但使用不同的参数集。
function Test {
param(
[Parameter(ParameterSetName="set1",Position=0)][int]$a,
[Parameter(ParameterSetName="set1",Position=1)][int]$b,
[Parameter(ParameterSetName="set1",Position=2)][int]$c,
[Parameter(ParameterSetName="pipeline",ValueFromPipeLine=$true,Position=0)][Hashtable]$obj
)
if ($obj -ne $null) { return Test @obj }
write-host "a=" $a
write-host "b=" $c
write-host "c=" $c
}
Test (Get-TestArgs)
Get-TestArgs | Test
Test 1 2 3
根据您需要创建的函数数量以及打算如何调用它们,您可以选择其中一种解决方案。就个人而言,最后一个似乎是我最优雅的选择。我会选择管道:Get-TestArgs | Test
在PowerShell中看起来比Test (Get-TestArgs)
更自然。
例如,许多Azure PowerShell commands旨在以这种方式工作。
答案 1 :(得分:3)
我相当确定这不能用splatting完成,因为:
我真的认为你能做的最好的事情是:
function Test() {
param($a, $b, $c)
Write-Host 'A' $a
Write-Host 'B' $b
Write-Host 'C' $c
}
function Get-TestArgs() { @(1,2,3) }
$p = Get-TestArgs; Test @p
答案 2 :(得分:0)
我看到这篇文章的发布时间可以追溯到3年前,但是以防万一其他人(例如我)遇到这篇文章时,以下解决方案有效,并且已经在Powershell 5和3控制台(powershell.exe)中进行了测试-版本3)
使用委托并调用它:
&{ param($hashtable) &functionToRun @hashtable} (functionReturningHashTable)
基于最初发布的代码:
function Get-TestArgs() { return @{a=1;b=2;c=3} }
function Test($a, $b, $c) {
Write-Host 'A' $a
Write-Host 'B' $b
Write-Host 'C' $c
}
&{ param($hashtable) &Test @hashtable} (Get-TestArgs)
返回:
A 1
B 2
C 3
您甚至可以将所需的所有命令放在最后的括号中。
假设当前目录中有3个文件a,b,c(如果未使用以下代码创建它们):
'a','b','c' | % { New-Item -Path $_ -ItemType File }
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 15/12/2019 14:34 0 a
-a---- 15/12/2019 14:34 0 b
-a---- 15/12/2019 14:34 0 c
然后您可以执行以下命令:
&{ param([hashtable]$hashtable) &Test @hashtable} (gci | group -AsHashTable -Property Name)
它返回:
A a
B b
C c
使用以下代码删除创建的文件:
'a','b','c' | % { Remove-Item -Path $_ }
此致
答案 3 :(得分:-1)
通过将哈希表通过管道传递到ForEach-Object(别名%)并使用自动变量$ PSItem(别名$ _),可以很容易地实现(而无需(用户定义)变量)。
def coins(n, m_25, m_10, m_5, m_1, m_tot, count=1):
if m_tot == n:
count +=1
return count
if m_tot > n:
return count
count = coins(n, m_25+1, m_10, m_5, m_1, m_tot+25, count)
count = coins(n, m_25, m_10+1, m_5, m_1, m_tot+10, count)
count = coins(n, m_25, m_10, m_5+1, m_1, m_tot+5, count)
count = coins(n, m_25, m_10, m_5, m_1+1, m_tot+1, count)
return count
def get_coins(n, m_25, m_10, m_5, m_1, m_tot):
return coins(n, m_25, m_10, m_5, m_1, m_tot)
print(f"Coins: {get_coins(10, 2, 3, 1, 5, 2)}")
# >> 6
都返回的
Get-TestArgs | ForEach-Object {Test @PSItem}
Get-TestArgs | % {Test @_}