我有一个CSV设备缺少安全更新以及更新发布的日期和kb编号。
devicename,date,kb
Desktop1,9/12/17,KB4011055
Desktop1,9/12/17,KB4038866
Desktop2,9/12/17,KB4011055
Desktop2,6/13/17,KB3203467
我正在尝试编译缺少过去30天内发布的更新的设备列表,但排除了也缺少旧版更新的设备。所以在上面的例子中,我想要的唯一设备是Desktop 1。 我知道我可以做这样的事情来查看30天窗口以下的设备,但仍然包含其他条目超过30天的设备。
$AllDevices | Where-Object {[datetime]$_.date_released -gt ((get-date).adddays(-30))}
我在想我可以使用Group-Object devicename
将所有设备组合在一起,但我不确定如何从那里查看日期。
有什么想法吗?
答案 0 :(得分:2)
假设$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
从组[datetime[]]
的每个成员的日期时间字符串(.date
)创建一个日期时间对象数组$_.Group
。< / p>
$_.Group
是组成该组的输入对象的集合,即使.date
直接应用于$_.Group
,.date
也是-le (Get-Date).AddDays(-30)
在每个集合成员上访问属性,并在数组中收集结果 - 这个方便的快捷语法称为member enumeration,并在PSv3中引入。 -le
过滤该数组仅返回日期超过30天的成员;请注意,应用于数组值 LHS的-not
会返回过滤的子数组,而不是布尔值。
-le
否定了$False
比较的结果,该结果强制将过滤后的数组解释为 Boolean ,如果布尔,则计算结果为$True
数组为空,否则为-le
;换句话说:如果一个或多个小组成员的日期超过30天,则$True
比较将评估为-not
作为布尔值,.Name
否定。
这导致包含至少1个超过30天的日期的组(和其他设备)从进一步的管道处理中删除。
Select-Object
然后只接收其成员都具有最近30天内日期的组对象,并使用calculated properties (via hashtable literals (@{...}
) with standardized entries)构造输出对象:
组对象的Group-Object
属性包含传递给devicename
的分组属性的值,在这种情况下是输入对象的@{ l='devicename'; e='Name' }
属性; .Name
只需将devicename
媒体资源重命名为@{ l='kbs'; e={ $_.Group.kb } }
。
kbs
然后构造一个kb
属性,其中包含来自每个组成员的{ ... }
值的数组,通过成员枚举检索脚本块Select-Object
请注意,[pscustomobject]
输出devicename
个实例仅包含明确定义的属性;在这种情况下,kbs
和ShowModal
。
答案 1 :(得分: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
}
}
}