powershell 如何在多维数组中添加哈希表?无法通过成员访问枚举分配值

bvuwiixz  于 2023-05-07  发布在  Shell
关注(0)|答案(1)|浏览(149)

我在向多维数组中添加哈希表时遇到了问题。我编写了以下代码:

$Data = @{BIBs = @(
    @{$BIB = @{BIBName=$BIBName}, 
    @{Standort = $Standort}, 
    @{Bücher = @(
        @{BuchName = $BuchName; 
        Autor = $Autor
        })
    }}
)}

这段代码运行并创建了一个输出,我将其存储在JSON中:

{
    "BIBs": [
        {
            "BIB1": [
                {
                    "BIBName": "123"
                },
                {
                    "Standort": "123"
                },
                {
                    "Bücher": [
                        {
                            "Autor": "123",
                            "BuchName": "123"
                        }
                    ]
                }
            ]
        },
        {
            "BIB2": [
                {
                    "BIBname": "345"
                },
                {
                    "Standort": "345"
                },
                {
                    "Bücher": [
                        {
                            "Autor": "345",
                            "Buchname": "345"
                        }
                    ]
                }
            ]
        }
    ]
}

我有额外的代码添加另一个哈希表数组“BIBs”,你可以看到。

$jsonfile = "C:\Skripte\bibV2-1000.json"
$Data = Get-Content $jsonfile | ConvertFrom-Json
$Data.BIBs += New-Object -TypeName PSObject -Property @{
    $BIB = @{BIBname=$BIBName}, @{Standort=$Standort},
           @{Bücher = @(@{Buchname=$BuchName;Autor=$Autor})}
}

当输出像上面一样时,我无法向“Bücher”添加另一个哈希表。我查了“Bücher”的类型

$data.BIBs.BIB1.Bücher.GetType()

它实际上是一个数组

IsPublic IsSerial Name     BaseType
-------- -------- ----     --------
True     True     Object[] System.Array

我尽力了

$Data.BIBs.BIB1.Bücher += @{Person="Max";Alter="35"}

添加一个新的哈希表,就像我对“BIB2”所做的那样,但我得到了错误:

The property 'Bücher' cannot be found on this object. Verify that the property
exists and can be set.
At line:5 char:1
+ $data.BIBs.BIB1.Bücher += @{Motor="asdf";pers="345"}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyAssignmentException

你知道我怎么把@{Person="Max";Alter="35"}加到“Bücher”上吗

6mw9ycah

6mw9ycah1#

tl;dr

不支持 * 通过 member-access enumeration 设置 * 键/属性值(见下文)。
必须获取要显式修改.Bücher属性的具体对象

($Data.BIBs.BIB1 | ? Bücher).Bücher += @{ BuchName='neues Buch'; Autor='Johann Doe' }

注:假设:

  • 数组$Data.BIBs.BIB1中只有 one 个元素具有.Bücher属性(key)
  • 如果属性/键确实存在,则它是 * 非空 *,因此在布尔上下文中是“truthy”,例如传递给?Where-Object)的表达式;与成员访问枚举类似,这种简化的Where-Object语法(? Bücher而不是? { $_.Bücher })是PSv 3+的特性,称为simplified syntax

Mathias R. Jessen在对这个问题的评论中提供了关键的指针:

PowerShell在 collection-valued 属性的点表示法方面故意不对称,用于 getting 值与 * 设置 * 值。
*getting 上,PSv 3+应用member-access enumeration,简而言之,它允许您访问 collection 上的属性,并隐式地从 each element IN that collection 获取该属性的值,结果收集在 array 中。
*设置 * 时,成员访问枚举 * 不 * 应用;理由是无意修改数据的风险太高-请参见GitHub issue #5271,特别是PS团队核心成员的评论。

不幸的是,当前的错误消息并没有告诉你
它源于这样一个事实,即当试图在集合级别 * 设置 * 一个属性时,该属性只会 * 直接在集合 * 上(而不是在其元素上)查找,而它(通常)并不存在。
让我们看一个简化的例子:

$data = @{ # a hashtable
  a = ( # array of hashtables
    @{ b1 = 'b1' },
    @{ b2 = 'b2' },
    @{ b3 = 
      @{ b31 = 'b31' }, @{ b32 = 'b32' } # array of hashtables
    }
  )
}

在****上,一切工作正常**:

PS> $data.a.b3

Name                           Value                                                                                                                                                                                                                            
----                           -----                                                                                                                                                                                                                            
b31                            b31                                                                                                                                                                                                                              
b32                            b32

即使$data.a是一个[object[]]数组,也会在其 * 元素 * 中找到具有.b3属性的对象(哈希表),并输出该对象的.b3值。
这是成员访问枚举的作用(尽管更典型的用法是属性存在于数组的 all 元素上,以及单个值被收集到[object[]]数组中)。

在 * 设置*时,PowerShell放弃了成员访问枚举,因此**只能 * 在[object[]]示例$data.a上直接查找.b3属性失败,当然,数组没有.b3属性:

PS> $data.a.b3 += @{ b33 = 'b33' }  # Try to add an element; !! FAILS

The property 'b3' cannot be found on this object. 
Verify that the property exists and can be set.
...

相关问题