2017-10-07 62 views
1

我有一個缺少安全更新的設備的CSV以及更新的發佈日期和kb數。Powershell Group-Object - 使用多個對象的篩選器

devicename,date,kb 
Desktop1,9/12/17,KB4011055 
Desktop1,9/12/17,KB4038866 
Desktop2,9/12/17,KB4011055 
Desktop2,6/13/17,KB3203467 

我試圖編譯缺少已在過去30天內已發佈的更新設備的列表,但排除也缺少較舊的更新設備。所以在上面的例子中,我想要的唯一設備是桌面1. 我知道我可以做這樣的事情來查看那些在30天窗口之下的設備,但仍然會包含其他條目超過30天的設備。

$AllDevices | Where-Object {[datetime]$_.date_released -gt ((get-date).adddays(-30))} 

我想我可以用Group-Object devicename將所有的設備連接在一起,但我不知道如何從那裏檢查日期。 任何想法?

回答

1

的假設是,$AllDevices被分配從一些輸出等
Import-Csv c:\path\to\some.csv和PSv3 +被使用。

$AllDevices | Group-Object devicename | Where-Object { 
    -not ([datetime[]] $_.Group.date -le (Get-Date).AddDays(-30)) 
} | Select-Object @{ l='devicename'; e='Name' }, @{ l='kbs'; e={ $_.Group.kb } } 

與樣品輸入,這產生了:

devicename kbs     
---------- ---     
Desktop1 {KB4011055, KB4038866} 

說明:

  • Group-Object devicename組中的所有輸入對象通過設備名稱,其輸出[Microsoft.PowerShell.Commands.GroupInfo]實例的集合每個表示共享給定設備名稱的所有輸入對象(例如Desktop1) - 見Get-Help Group-Object

  • Where-Object調用然後用於清除包含日期早於30天的對象的組。

    • [datetime[]] $_.Group.date創建的日期 - 時間對象的數組選自$_.Group的每一個成員的日期 - 時間字符串(.date[datetime[]]

      • 注意$_.Group集合輸入對象組成的組,並且即使.date被直接施加到$_.Group,所述.date屬性是基於每個收集構件訪問和結果收集在的一個數組 - 這個方便的快捷方式語法被稱爲member enumeration,並在PSv3中引入。
    • -le (Get-Date).AddDays(-30)過濾該數組只返回日期超過30天的成員;請注意,-le應用於陣列值 LHS返回已過濾的子陣列,而非布爾值。

    • -not否定-le比較,這迫使過濾陣列作爲布爾,其評估對$False如果數組爲空,否則$True的解釋的結果;換句話說:如果一個或多個組成員的日期超過30天,則-le比較的結果將以$True作爲布爾值,否則-not將會被否定。
      這會導致包含至少1個30天以上的日期的組(和其它設備)從進一步的流水線處理中移除。

  • Select-Object然後只接收那些對象組,其成員都落入最後30天內的日期,並使用calculated properties (via hashtable literals (@{...}) with standardized entries)構建輸出對象:

    • 一組對象的.Name屬性包含分組屬性的值傳遞給Group-Object,在這種情況下是輸入對象'devicename屬性; @{ l='devicename'; e='Name' }只是將.Name屬性重命名爲devicename

    • @{ l='kbs'; e={ $_.Group.kb } }然後構造一個kbs屬性,通過腳本塊包含陣列從各組,由構件枚舉檢索成員kb{ ... }

    • 請注意,只有含Select-Object輸出[pscustomobject]實例明確定義的屬性;在這種情況下,devicenamekbs

1

我提出其他的解決辦法:

import-csv "C:\temp\test.csv" | 
    select *, @{N="Date";E={[DateTime]$_.Date}} -ExcludeProperty "Date" | 
       group devicename | 
       %{ 
        if (($_.Group | where Date -le (Get-Date).AddDays(-30)).Count -eq 0) 
        { 
         $LastUpdate=$_.Group | sort Date, kb -Descending | select -First 1 
         [pscustomobject]@{ 
         DeviceName=$LastUpdate.DeviceName 
         DateLastUpdate=$LastUpdate.Date 
         LastUpdate=$LastUpdate.Kb 
         UpdateList=$_.Group.Kb -join ', ' 
         Group=$_.Group 
         } 
        } 

       }