2017-10-07 59 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 
         } 
        } 

       }