【问题标题】:Looping through properties inside a PSObject in PowerShell (from json)在 PowerShell 中循环访问 PSObject 内的属性(来自 json)
【发布时间】:2020-04-18 04:31:18
【问题描述】:

在 PowerShell 中打开 .json 文件后,我得到了一个名为 $json_sitesandsnets 的新 PSObject。最终,我想做的是遍历每个站点(奥兰多、丹佛),并遍历它们的每个子网,然后做一些事情。最初,我需要使用 New-ADReplicationSubnet cmdlet 为 Active Directory 中的相应站点创建这些子网。我已经使用它创建了一个子网,但我有一个更大的站点和子网列表,我将使用它。这个例子只是一个小的精简版发布在这里。一旦我弄清楚如何访问对象值中的这些子网,我可能只是将每个子网列表提供给 New-ADReplicationSubnet。但我真的希望能够循环遍历每个子网以用于其他目的。我想这可能并不难做到,只要你知道怎么做。

这是原始的 json:

{
"Orlando":  [
                        "10.10.10.0/24",
                        "10.10.20.0/24",
                        "10.10.30.0/24",
                        "10.10.40.0/24"
                    ],
"Denver":  [
                       "10.0.70.0/24",
                       "10.0.80.0/24",
                       "10.0.90.0/24",
                       "10.0.100.0/24",
                       "10.0.110.0/24",
                       "10.0.120.0/24"
                   ]
}

我得到 PSObject 的属性如下:

$json_sitesandsnets.psobject.properties

PSObject properties

当我在 VSCode 中运行 Debug 时,我可以看到 PSObject 和子网列表(数组): seeing this in Debug

这是一些代码,它的名称没有问题(Write-Host $site.Name)。如您所见,我尝试了几种不同的方法来访问这些子网,它们是每个站点的值。我就是想不通。我已经阅读了很多关于循环访问 PSObject 的文章和论坛主题,但似乎无法找到访问和循环访问作为 PSObject 值的数组的最佳答案。我觉得我真的很亲近。

foreach ($site in $json_sitesandsnets.PSObject.Properties) {
Write-Host $site.Name
$site| get-member -type NoteProperty | foreach-object {
    $subnet = $site."$($_.Value)"
    Write-Host $subnet
    Write-Host $_.Value
}
}

【问题讨论】:

  • 如果您(在循环内)执行 $site.Value | 会发生什么?通用
  • $site.value 绝对是我需要去的地方。
  • 我懒得在我的电脑上设置你的机箱。但我希望 $site.value 是某种带有列表、数组或由 IP 地址组成的东西的容器。然后,您需要编写一个内部循环来一次提取一个并格式化它们。

标签: arrays json powershell loops psobject


【解决方案1】:

我不认为 json 可能是这样的? powershell 中生成的对象数组会更容易使用。它几乎可以是一个 csv。

[
  {
    "site": "Orlando",
    "subnets": [
      "10.10.10.0/24",
      "10.10.20.0/24",
      "10.10.30.0/24",
      "10.10.40.0/24"
    ]
  },
  {
    "site": "Denver",
    "subnets": [
      "10.0.70.0/24",
      "10.0.80.0/24",
      "10.0.90.0/24",
      "10.0.100.0/24"
    ]
  }
]


cat sites.json | convertfrom-json     

site    subnets
----    -------
Orlando {10.10.10.0/24, 10.10.20.0/24, 10.10.30.0/24, 10.10.40.0/24}
Denver  {10.0.70.0/24, 10.0.80.0/24, 10.0.90.0/24, 10.0.100.0/24}

【讨论】:

  • 这真的很有趣...我喜欢这种结构,如果需要,可能最终会这样做。
【解决方案2】:

您可以通过使用站点名称进行索引来做到这一点。 $json_sitesandsnets.($site.Name)

我也会在foreach 中使用$json_sitesandsnets.PSObject.Properties.Name 而不是$json_sitesandsnets.PSObject.Properties,以简化事情:

foreach ($site in $json_sitesandsnets.PSObject.Properties.Name) {
    Write-Host $site
    foreach ($subnet in $json_sitesandsnets.$site){
        Write-Host "logic for subnet $subnet"
    }
    # alternatively
    $json_sitesandsnets.$site | ForEach-Object {
        Write-Host "logic for subnet $_ (foreach-object)"
    }
}

编辑:您的方法不起作用,因为子网是字符串数组,并且子网未命名为属性/注释属性。您可以通过执行以下操作来查看这一点。

# This tells you it's an array of "objects" with properties Length, Rank etc
Get-Member -InputObject $json_sitesandsnets.Denver

# This pipes the array elements, telling you they are strings with Length property
# In powershell strings are an object that only have properties Chars/Length
$json_sitesandsnets.Denver | Get-Member

# To only return the types
$json_sitesandsnets.Denver.GetType()
$json_sitesandsnets.Denver[0].GetType()

【讨论】:

  • 感谢您的输入,感谢那些帮助我更好地理解对象的附加命令。
【解决方案3】:

在我看来,你想要的是这个。

foreach ($site in $json_sitesandsnets.PSObject.Properties) {
    Write-Host $site.Name -ForegroundColor Cyan
    $site.Value | Out-String | Write-Host 
}

输出

对于子网值,not 属性是 OrlandoDenver。 你的那部分是对的,但是你的$site| get-member 线不应该在那里。相反,您可以直接通过$site.value 访问该值。 如果你需要做更多的事情,你可以循环这些值,像这样:

$index = 0
Foreach ($subnet in $site.Value) {
    Write-Host "$($index): $subnet"
    $index+=1
}

输出

【讨论】:

  • 我相信这将是我所需要的。昨天发布后,我正在查看它,我突然想到 Site.Value 应该给我这些子网。然后我看到了你的帖子,并确认了。
  • 你能帮我理解为什么我们需要索引吗? .Value(子网)已经看起来是一个数组(请参阅调试屏幕截图)。我能够像这样遍历这些子网: foreach ($site in $json_sitesandsnets.PSObject.Properties) { Write-Host $site.Name -ForegroundColor Cyan foreach ($subnet in $site.Value) { Write-Host $subnet } }
  • foreach ($site in $json_sitesandsnets.PSObject.Properties) { Write-Host $site.Name -ForegroundColor Cyan foreach ($subnet in $site.Value) { Write-Host $subnet } }
  • @stackDram 你绝对不需要索引任何东西。这一点只是为了演示在我的主要示例中遍历所有子网正弦的基本循环,我使用 $site.Value | Out-String | Write-Host 绕过了 Foreach
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-03
  • 1970-01-01
  • 1970-01-01
  • 2020-11-10
  • 2021-06-20
相关资源
最近更新 更多