簡體   English   中英

PowerShell - 如何將兩個自定義對象的屬性添加在一起以使用

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

我正在使用一些 PowerShell 函數從一些 REST API 端點獲取數據。 遍歷第一個查詢的結果允許我使用id字段來檢索第二個查詢中的匹配結果,但是,第二個查詢的返回結果沒有任何與原始結果集匹配的屬性,所以我不'認為我不能執行 JOIN 或類似的操作。

例如,假設查詢第一個 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

並使用ID = 1查詢第二個 REST 端點,我們將以下內容存儲在$b中:

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

我想做的是結合兩者的屬性,一次一條記錄,所以在我檢索$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

由於代碼然后遍歷$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

在我看來,這將相當簡單,但是,我查看了許多不同的帖子和網站,但似乎沒有一個可以幫助我實現我想要的,或者更可能我只是誤解了諸如Add-Member之類的方法可能會起作用在多個管道循環中,或錯過盲目明顯的內容。

我最接近的是下面的代碼,它實際上產生了一個數組或哈希表(取決於我如何初始化$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"
    }
}

這會產生一個鍵/值表,例如:

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

這意味着我最終會得到一個數組數組(或哈希表的哈希表)。 雖然我認為我仍然可以使用這種類型的數據格式,但我很想了解我需要做什么來實現我的初始目標。

更新

獲取$a$b的代碼如下。 有一些封裝 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}}
}

更新 2

這是完整的代碼,它可以工作,但有點啰嗦,可能真的效率低下,並產生一個哈希表的哈希表:

$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
}

更新 3

在@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
        }
    }
}

這會導致屏幕轉儲(我猜是管道清理):

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

...

所以,我想這已經接近我想要的了,但還沒有真正實現。 我現在需要弄清楚如何處理管道輸出......這與思維方式的改變有很大關系,所以可能需要一些頭緒。

更新 4 - 可能的解決方案

好的,因此擴展了上面的代碼塊,我創建了一些額外的邏輯來將pscustomobject的輸出通過管道傳輸到 CSV 文件。 最終目的是根據前一天的配置檢查各個端點的狀態,看看是否有任何變化(因為它確實發生了變化,而且通常在管理員不知情的情況下!)。

分配一個變量來存儲嵌套foreach循環的結果。 然后將其用於導出到 CSV。 我在腳本的開頭添加了一些進一步的邏輯來檢查文件是否存在,如果存在則刪除今天的配置文件,這樣腳本會在每天意外運行多次時創建一個新的配置文件.

一旦主循環完成,今天和昨天的文件將被重新導入,並使用Compare-Object CmdLet 查看是否有任何更改。 如果兩個文件之間存在差異,我可能會添加一些發送電子郵件代碼。

$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"
}

從外觀上看,這可能會為您提供所需的內容:

$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
        }
    }
}

基本上可以在運行時創建對象,而不是收集結果$a$b然后加入/合並它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM