将 ValueFromRemainingArguments 作为哈希表获取

Get ValueFromRemainingArguments as an hashtable

使用 [parameter(ValueFromRemainingArguments=$true)] 可以将传递给函数的所有剩余参数作为列表放入变量中。

如何将剩余的参数作为哈希表类型获取,例如对于像 Function -var1 value1 -var2 value2 这样的输入?

根据 Ansgars 评论更新。

一种可能性是在函数内构建哈希-table。这是一个例子:

function MyFunction
{
    [CmdletBinding()]
    param([parameter(ValueFromRemainingArguments=$true)] $allparams)

    process
    {
        $myhash = @{}
        for ($i = 0; $i -lt $allparams.count; $i+=2)
        {
            $myhash[($allparams[$i]-replace '^-+')] = $allparams[$i+1]
        }
    }
    end
    {
        $myhash
    }
}

我们使用 for 循环解析参数 $allparams 中的参数,并检索 key/value 对以形成散列 table,然后在结束块中显示它。

MyFunction -var1 10 -var2 30 -var3 hello

Name                          Value                     
----                          -----                     
var1                          10                        
var3                          hello                     
var2                          30 

有多种方法可以实现这一点。以下解决方案支持参数:

  • 简单值(单项)
  • 数组值
  • 空值(开关)

脚本:

function testf {

    param(
        $name = "Frode",
        [parameter(ValueFromRemainingArguments=$true)]
        $vars
    )

    "Name: $name"
    "Vars count: $($vars.count)"
    "Vars:"

    #Convert vars to hashtable
    $htvars = @{}
    $vars | ForEach-Object {
        if($_ -match '^-') {
            #New parameter
            $lastvar = $_ -replace '^-'
            $htvars[$lastvar] = $true
        } else {
            #Value
            $htvars[$lastvar] = $_
        }
    }

    #Return hashtable
    $htvars

}

testf -simplepar value1 -arraypar value2,value3 -switchpar

输出:

Name: Frode
Vars count: 5
Vars:

Name      Value
----      -----
arraypar  {value2, value3}
switchpar
simplepar value1

编辑:修改了分配给哈希表键的默认值:$htvars[$lastvar] = $true。使用 $true 作为 switch 参数的默认帐户,可以使生成的 Hastable 更“splattable”。

这很棘手,因为使用 [Parameter(ValueFromRemainingArguments=$true)] 意味着这是一个高级函数,$args 不能用于高级函数。

但是如果您想要所有指定参数及其值的哈希表,您可以简单地使用 $PSBoundParameters,如下所示:

function foo {
    [cmdletbinding()]

    param( 
        [Parameter(Position=0)]       
        $Name,

        [Parameter(Position=1,ValueFromRemainingArguments=$true)]
        $LastName
    )

    "PSBoundParameters : " 
    $PSBoundParameters

}
foo -Name Mike Jordan Jones

结果如下:

PSBoundParameters : 

Key                                               Value                                           
---                                               -----                                           
Name                                              Mike                                            
LastName                                          {Jordan, Jones}         

这是您要实现的目标吗?

此方法有很多注意事项,但我只是想表明 ConvertFrom-StringData 也可以在这里考虑。

function Convert-StringToHashTable {

    param(
        [parameter(ValueFromRemainingArguments=$true)]
        [string]$string
    )

    $string -replace "(^| )-","`r`n" | ForEach-Object{$_ -replace "(\w+) (.*)",'='} | ConvertFrom-StringData
}

Convert-StringToHashTable -var1-5 value1 -var2 "value2 or 3"

上面的输出是

Name                           Value                                                                                                                                        
----                           -----                                                                                                                                        
var2                           value2 or 3                                                                                                                                      
var1-5                         value1   

我们将所有剩余的参数作为一个字符串。然后我们将字符串拆分为出现在行首或 space 之后的 -。 (这说明了另一个答案中提到的 Ansgar 等作品中间的破折号)。然后我们把第一个词后面的第一个space转换成等号。这将生成 ConvertFrom-StringData 期望的键值对字符串。

已知注意事项

  1. 如果您尝试像 Frode 的回答那样发送数组,这将不起作用。他可以处理这些。