简体   繁体   English

PowerShell - 如何将两个自定义对象的属性添加在一起以使用

[英]PowerShell - How to add the properties of two custom objects together to create a single merged custom object using

I am using some PowerShell functions to get data from some REST API endpoint.我正在使用一些 PowerShell 函数从一些 REST API 端点获取数据。 Iterating through the results of the first query allows me to use an id field to retrieve matching results in the second query, however, the returned results of the second query do not have any properties that would match the original set of results, so I don't think I could perform a JOIN or something like that.遍历第一个查询的结果允许我使用id字段来检索第二个查询中的匹配结果,但是,第二个查询的返回结果没有任何与原始结果集匹配的属性,所以我不'认为我不能执行 JOIN 或类似的操作。

For example, assume the results of querying the first REST endpoint are stored in $a .例如,假设查询第一个 REST 端点的结果存储在$a中。

$a = 
ID  Title                  Location  Internal IP Address
--  -----                  --------  -------------------
1   Endpoint 1             UK        10.0.0.1
2   Endpoint 2             US        10.1.0.1
3   Endpoint 3             AUS       10.2.0.1

And using ID = 1 to query the second REST endpoint, we get the following stored in $b :并使用ID = 1查询第二个 REST 端点,我们将以下内容存储在$b中:

$b = 
NATed IP Address Last Provisioned Time
---------------- ---------------------
1.2.3.4          2022-02-10T04:09:31.988909+01:00

What I could like to do is combine the properties of both, one record at a time, so after I have retrieved $b I would create $c , which would look something like this:我想做的是结合两者的属性,一次一条记录,所以在我检索$b之后,我会创建$c ,它看起来像这样:

$c =
ID  Title       Location  Internal IP Address NATed IP Address Last Provisioned Time
--  -----       --------  ------------------- ---------------- ---------------------
1   Endpoint 1  UK        10.0.0.1            1.2.3.4          2022-02-10T04:09:31.988909+01:00

As the code then iterates through the results of $a , so I should build up a full merged object and after three iterations of $a , we should end up with something like:由于代码然后遍历$a的结果,所以我应该建立一个完整的合并对象,并且在$a三个迭代之后,我们应该最终得到类似的结果:

$d =
ID  Title       Location  Internal IP Address NATed IP Address Last Provisioned Time
--  -----       --------  ------------------- ---------------- ---------------------
1   Endpoint 1  UK        10.0.0.1            1.2.3.4          2022-02-10T04:09:31.988909+01:00
2   Endpoint 2  US        10.1.0.1            1.2.3.5          2022-02-10T04:09:31.988909+01:00
3   Endpoint 3  AUS       10.2.0.1            1.2.3.6          2022-02-10T04:09:31.988909+01:00

It feels to me that this would be reasonably simple, however, I have looked at many different posts and sites, but none seem to help me achieve what I want, or more probably I am simply misunderstanding how methods such as Add-Member might function within multiple piped loops, or missing the blindly obvious.在我看来,这将相当简单,但是,我查看了许多不同的帖子和网站,但似乎没有一个可以帮助我实现我想要的,或者更可能我只是误解了诸如Add-Member之类的方法可能会起作用在多个管道循环中,或错过盲目明显的内容。

The closest I have come is the following code, which actually results in an Array or Hashtable (depending on how I initialise the $collection variable), but the results are similar:我最接近的是下面的代码,它实际上产生了一个数组或哈希表(取决于我如何初始化$collection变量),但结果是相似的:

$collection = @{}

foreach ($item in $a) {
    $collection += @{
        "Title" = $item.Title
        "Location" = $item.Location
        "Internal IP Address" = $item."Internal IP Address"
    }
}

foreach ($item in $b) {
    $collection += @{
        "NATed IP Address" = $item."NATed IP Address"
        "Last Provisioned Time" = $item."Last Provisioned Time"
    }
}

Which results in a key/value table such as:这会产生一个键/值表,例如:

Name                           Value
----                           -----
ID                             1
Title                          Endpoint 1
Internal IP Address            10.0.0.1 
Location                       UK
NATed IP Address               1.2.3.4
Last Provisioned Time          2022-02-10T03:21:29.265257+01:00

What this means is that I will end up with an array of arrays (or a hashtable of hashtables).这意味着我最终会得到一个数组数组(或哈希表的哈希表)。 While I think I could still work with this type of data format, I would be intrigued to understand what I need to do to achieve my initial goal.虽然我认为我仍然可以使用这种类型的数据格式,但我很想了解我需要做什么来实现我的初始目标。

UPDATE更新

The code to get $a and $b is as follows.获取$a$b的代码如下。 There are some functions that wrap the API calls:有一些封装 API 调用的函数:

$a = Get-Endpoints -Creds $Credentials -URI $FQDN

$a| ForEach-Object {
    $b = Get-ProvisioningInfoEndpoint -Creds $Credentials -URI $FQDN -id $_.id |
        Select-Object -Property @{Name="NATed IP Address";Expression={$_.ip}}, @{Name="Last Provisioned Time";Expression={$_.ts_created}}
}

UPDATE 2更新 2

Here is the full code, which works but is kinda long winded and probably really inefficient, and results in a hashtable of hashtables:这是完整的代码,它可以工作,但有点啰嗦,可能真的效率低下,并产生一个哈希表的哈希表:

$a = Get-Endpoints -Creds $Credentials -URI $FQDN

$a| ForEach-Object {
    $b = Get-ProvisioningInfoEndpoint -Creds $Credentials -URI $FQDN -id $_.id |
        Select-Object -Property @{Name="NATed IP Address";Expression={$_.ip}}, @{Name="Last Provisioned Time";Expression={$_.ts_created}}

    $EndpointSelectedData = $_ | Select-Object -Property ID, @{Name="Title";Expression={$_.title}}, @{Name="Location";Expression={$_.location}}, @{Name="Internal IP Address";Expression={$_.ip}}

    $c = @{}
    foreach ($EndpointData in $EndpointSelectedData) {
        $c += @{
            "ID" = $EndpointData.id
            "Title" = $EndpointData.Title
            "Location" = $EndpointData.Location
            "Internal IP Address" = $EndpointData."Internal IP Address"
        }
    }

    foreach ($ProvisionedD in $ProvisionedData) {
        $collection += @{
            "NATed IP Address" = $ProvisionedD."NATed IP Address"
            "Last Provisioned Time" = $ProvisionedD."Last Provisioned Time"
        }
    }

    $d = $d + @{"Node_$i" = $c}
    $i = $i + 1
}

UPDATE 3更新 3

After a suggested answer from @Santiago, and a pointer from @iRon, I now have the following code:在@Santiago 提出建议的答案和@iRon 的指针后,我现在有以下代码:

$Endpoints = Get-Endpoints -Creds $Credentials -URI $FQDN

foreach($i in $Endpoints) {
    foreach($z in Get-ProvisioningInfoEndpoint -Creds $Credentials -URI $FQDN -Id $i.id) {
        [pscustomobject]@{
            'ID'                    = $i.Id
            'Title'                 = $i.Title
            'Location'              = $i.Location
            'Internal IP Address'   = $i.Ip
            'NATed IP Address'      = $z.Ip
            'Last Provisioned Time' = $z.Ts_Created
        }
    }
}

This results in a dump to the screen (which I guess is the pipeline clearing) of:这会导致屏幕转储(我猜是管道清理):

ID                    : 1
Title                 : Endpoint 1
Location              : UK
Internal IP Address   : 10.0.0.1
NATed IP Address      : 1.2.3.4 
Last Provisioned Time : 2022-02-10T04:09:32.126357+01:00

ID                    : 2
Title                 : Endpoint 2
Location              : US
Internal IP Address   : 10.1.0.1
NATed IP Address      : 1.2.3.5
Last Provisioned Time : 2022-02-10T04:21:32.657364+01:00

ID                    : 3
Title                 : Endpoint 3
Location              : Aus
Internal IP Address   : 10.2.0.1
NATed IP Address      : 1.2.3.6
Last Provisioned Time : 2022-02-10T04:09:31.990202+01:00

...

So, I guess this is getting close to what I want, but still not really there.所以,我想这已经接近我想要的了,但还没有真正实现。 I now need to figure out how to handle the pipeline output... This is as much to do with a mindset change, so it might take some head scratching.我现在需要弄清楚如何处理管道输出......这与思维方式的改变有很大关系,所以可能需要一些头绪。

Update 4 - Possible solution更新 4 - 可能的解决方案

OK, so extending the chunk of code above, I have created some additional logic to pipe the output of the pscustomobject to a CSV file.好的,因此扩展了上面的代码块,我创建了一些额外的逻辑来将pscustomobject的输出通过管道传输到 CSV 文件。 The ultimate intention is to check the status of the various endpoints against their configuration from the previous day to see if anything had changed (as it does and often without the admin's knowledge!).最终目的是根据前一天的配置检查各个端点的状态,看看是否有任何变化(因为它确实发生了变化,而且通常在管理员不知情的情况下!)。

A variable is assigned to store the result of the nested foreach loops.分配一个变量来存储嵌套foreach循环的结果。 This is then used to export to a CSV.然后将其用于导出到 CSV。 I added some further logic at the beginning of the script to check to see if the file exists, and delete today's configuration file if it did, just so the script would create a fresh configuration file if it was run more than once a day by accident.我在脚本的开头添加了一些进一步的逻辑来检查文件是否存在,如果存在则删除今天的配置文件,这样脚本会在每天意外运行多次时创建一个新的配置文件.

Once the main loops are complete, today's and yesterday's files are imported back in and the Compare-Object CmdLet is used to see if there are any changes.一旦主循环完成,今天和昨天的文件将被重新导入,并使用Compare-Object CmdLet 查看是否有任何更改。 I will probably add some send email code if there is a diff between the two files.如果两个文件之间存在差异,我可能会添加一些发送电子邮件代码。

$DateStamp = get-date -Format FileDate
if (Test-Path -Path ".\endpoint-$($DateStamp).csv" -PathType Leaf) {
    Remove-Item -Path ".\endpoint-$($DateStamp).csv"
}
$Endpoints = Get-Endpoints -Creds $Credentials -ERMMgr $MgrFQDN

$result = foreach($i in $Endpoints) {
    foreach($z in Get-ProvisioningInfoEndpoint -Creds $Credentials -URI $FQDN -Id $i.id) {
        [pscustomobject]@{
            'ID'                    = $i.Id
            'Title'                 = $i.Title
            'Location'              = $i.Location
            'Internal IP Address'   = $i.Ip
            'NATed IP Address'      = $z.Ip
            'Last Provisioned Time' = $z.Ts_Created
        }
    }
}

$result | Export-Csv ".\endpoint-$DateStamp.csv"

if (Test-Path -Path ".\endpoint-$($DateStamp-1).csv" -PathType Leaf) {
    $InFile2 = Import-CSV -Path ".\endpoint-$($DateStamp-1).csv"
    Compare-Object -ReferenceObject $result -DifferenceObject $InFile2 -Property Title, "NATed IP Address" | Export-Csv ".\endpoint_diff-$DateStamp.csv"
}

By the looks of it, this might get you what you're looking for:从外观上看,这可能会为您提供所需的内容:

$result = foreach($i in Get-Endpoints -Creds $Credentials -URI $FQDN) {
    foreach($z in Get-ProvisioningInfoEndpoint -Creds $Credentials -URI $FQDN -Id $id.id) {
        [pscustomobject]@{
            'ID'                    = $i.Id
            'Title'                 = $i.Title
            'Location'              = $i.Location
            'Internal IP Address'   = $i.Ip
            'NATed IP Address'      = $z.Ip
            'Last Provisioned Time' = $z.Ts_Created
        }
    }
}

Basically the object can be created at runtime instead of collecting both results $a and $b to then join / merge them.基本上可以在运行时创建对象,而不是收集结果$a$b然后加入/合并它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在PowerShell中将新属性动态添加到自定义对象 - How to dynamically add new properties to custom object in PowerShell Powershell - 如何将多个对象添加到自定义 object 的属性中? - Powershell - how do I add multiple objects to a property on a custom object? 如何向现有的自定义 object 添加新属性并向 Powershell 中新添加的属性添加值? - How do I add new properties to an existing custom object and add values to the newly added properties in Powershell? 添加自定义对象Powershell - Add custom object powershell Powershell:向自定义对象添加行 - Powershell: Add lines to a custom objects 如何在PowerShell中为自定义对象创建自定义方法和项? - How to create a custom method and items for a custom object in powershell? Powershell:如何创建自定义对象并将其传递给PowerShell中的功能? - Powershell: How to create custom object and pass it to function in powershell? 如何将两个单维数组中的数字相加并将其添加到powershell中的第三个列表中 - How to add the numbers in two single-dimension arrays together and add that to a third list in powershell PowerShell自定义对象,在标准输出时忽略属性 - PowerShell Custom Object, ignore Properties at standard output 如何使用对象数组创建自定义哈希表-Powershell / cmd - How to create a custom hashtable with arrays of objects - powershell / cmd
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM