在不将散列或数组分配给变量的情况下进行Splatting

jpm*_*c26 3 powershell parameter-passing

我有一个返回哈希表的命令.像这样,例如:

function Get-TestArgs() { return @{a=1;b=2;c=3} }
Run Code Online (Sandbox Code Playgroud)

我想将其返回值用作我的其他函数的参数:

function Test($a, $b, $c) {
    Write-Host 'A' $a
    Write-Host 'B' $b
    Write-Host 'C' $c
}
Run Code Online (Sandbox Code Playgroud)

这可以通过PowerShell的splatting功能实现:

$testargs = @{a=1;b=2;c=3}
Test @testargs
Run Code Online (Sandbox Code Playgroud)

问题是我不想将哈希值分配给中间变量.

我想到的是这些方面的东西:

Test (some splat syntax)(Get-TestArgs)
Run Code Online (Sandbox Code Playgroud)

显然,这不起作用,因为它只是创建一个包含哈希的数组并传递:

Test @(Get-TestArgs)
Run Code Online (Sandbox Code Playgroud)

有没有办法实现这个目标?

我关心的原因

我正在编写将手动执行的指令.这些说明将调用脚本,但在调用之间仍有一些手动干预.因此,我希望尽量减少命令,以减少出现问题的风险,例如变量是其他命令或输入错误的遗留物.

qbi*_*bik 6

我认为没有变量就可以使用splatting.但是,实现您正在寻找的东西的解决方法很少.

  1. 编写一个包装函数,该函数将采用哈希表并调用"真实"函数.如果你想直接调用这个函数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
    
    Run Code Online (Sandbox Code Playgroud)
  2. 设计你的函数,使每个函数都将哈希表作为唯一参数 - 它是1的简化版本.它看起来有点难看 - 你只能Test通过查看它的声明来确定所需的参数.

    function Test ($hash)
    {
        write-host "a=" $hash.a
        write-host "b=" $hash.b
        write-host "c=" $hash.c
    }
    
    Test (Get-TestArgs)
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用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) 
    
    Run Code Online (Sandbox Code Playgroud)
  4. 利用参数集和管道.这与编写包装器类似,但目标函数也是包装器 - 根据参数集,它将正常执行或使用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
    
    Run Code Online (Sandbox Code Playgroud)

根据您需要创建的函数数量以及打算如何调用它们,您可以选择其中一种解决方案.就个人而言,最后一个似乎是我最优雅的选择.而且我会使用管道:Get-TestArgs | Test在PowerShell中看起来比较自然Test (Get-TestArgs).例如,许多Azure PowerShell命令都是以这种方式工作的.


Dav*_*kle 4

我相当确定这不能通过泼溅来完成,因为:

\n\n
\n

[Splatting] 表示,\xe2\x80\x9c 取接下来的任何字符并假设它们\xe2\x80\x99 是一个\n 变量名。假设该变量包含一个哈希表,并且键是参数名称。将它们展开,并将哈希表中的值提供给这些参数。\xe2\x80\x9d 这可能听起来像是一个冗长的解释,但\xe2\x80\x99s 是什么\xe2\x80\x99s正在发生。

\n
\n\n

我真的认为你能做的最好的事情就是:

\n\n
function Test() {\n    param($a, $b, $c)\n    Write-Host \'A\' $a\n    Write-Host \'B\' $b\n    Write-Host \'C\' $c\n}\n\nfunction Get-TestArgs() { @(1,2,3) }\n\n$p = Get-TestArgs; Test @p\n
Run Code Online (Sandbox Code Playgroud)\n