如何解决使用 Invoke-Expression 导航复杂/嵌套哈希表的更紧凑/优雅的方式?
我正在开发一个通过键层次结构的字符串输入来访问/修改嵌套哈希表的函数,如下所示:
putH() $hashtable "key.key.key...等" “新价值”
给定:
$c = @{
k1 = @{
k1_1 = @{
k1_1_1 = @{ key = "QQQQQ"}
}
}
}
function putH ($h,$hKEYs,$nVAL){
if ($hKEYs.count -eq 1) {
$bID = $hKEYs #match the last remaining obj in $hkeys
}
else {
$bID = $hKEYs[0] #match the first obj in $hekys
}
foreach ($tk in $h.keys){
if ($tk -eq $bID){
if ($hKEYs.count -eq 1){ #reached the last obj in $hkeys so modify
$h.$tk = $nVAL
break
}
else {
$trash,$hKEYs = $hKEYs #take out the first obj in $hkeys
$h.$tk = putH $h.$tk $hKEYs $nVAL #call the function again for the nested hashtale
break
}
}
}
return $h
}
function getH ($h,$hKEYs){
if ($hKEYs.count -eq 1) {
$bID = $hKEYs
}
else {
$bID = $hKEYs[0]
}
foreach ($tk in $h.keys){
if ($tk -eq $bID){
if ($hKEYs.count -eq 1){
$h = $h.$tk
break
}
else {
$trash,$hKEYs = $hKEYs
$h = getH $h.$tk $hKEYs
break
}
}
}
return $h
}
我像这样使用:
$s = "k1.k_1.k1_1_1" #custom future input
$s = $s.split(".")
putH $c ($s) "NEW_QQQQQ"
$getval = getH $c ($s)
我的问题:
有没有更优雅的方法来实现函数的结果……用 invoke-expression 说?
我试过 invoke-expression - 但无法通过它访问 hassstables(无论组合,嵌套引号如何)
$s = "k1.k_1.k1_1_1" #custom future input
iex "$c.$s"
退货
System.Collections.Hashtable.k1.k_1.k1_1_1
解决方法
不要使用Invoke-Expression
我会在底部回答你的问题,但我觉得有必要指出调用 Invoke-Expression
here is both dangerous,更重要的是,不必要。
您可以通过简单地将“路径”分成其各个部分('A.B.C'
-> @('A','B','C')
)然后一一取消引用它们来解析整个嵌套成员引用链(您不需要甚至不需要为此递归!):
function Resolve-MemberChain
{
param(
[Parameter(Mandatory = $true,ValueFromPipeline = $true)]
[psobject[]]$InputObject,[Parameter(Mandatory = $true,Position = 0)]
[string[]]$MemberPath,[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$Delimiter = '.'
)
begin {
$MemberPath = $MemberPath.Split([string[]]@($Delimiter))
}
process {
foreach($o in $InputObject){
foreach($m in $MemberPath){
$o = $o.$m
}
$o
}
}
}
现在您无需iex
即可解决问题:
$ht = @{
A = @{
B = @{
C = "Here's the value!"
}
}
}
$ht |Resolve-MemberChain 'A.B.C' -Delimiter '.'
您可以使用相同的方法来更新嵌套成员值 - 只需在最后一步停止,然后分配给 $parent.$lastMember
:
function Set-NestedMemberValue
{
param(
[Parameter(Mandatory = $true,position = 1)]
$Value,[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$Delimiter = '.'
)
begin {
$MemberPath = $MemberPath.Split([string[]]@($Delimiter))
$leaf = $MemberPath |Select -Last 1
$MemberPath = $MemberPath |select -SkipLast 1
}
process {
foreach($o in $InputObject){
foreach($m in $MemberPath){
$o = $o.$m
}
$o.$leaf = $Value
}
}
}
在行动中:
PS ~> $ht.A.B.C
Here's the value!
PS ~> $ht |Set-NestedMemberValue 'A.B.C' 'New Value!'
PS ~> $ht.A.B.C
New Value!
为什么您目前的方法不起作用?
您当前实现面临的问题是,一旦评估字符串文字 $c
,$c.$s
中的 "$c.$s"
就会被扩展 - 为避免这种情况,只需转义第一个$
:
iex "`$c.$s"
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。