PowerShell中Where-Object复杂与或逻辑筛选未达预期问题咨询
嘿,我立刻就发现问题出在哪了——你误用了PowerShell的运算符,还有一个小细节没注意到!
核心问题1:用错了字符串包含判断的运算符
PowerShell里的 -contains 是集合运算符,用来检查数组/集合里是否包含某个特定元素,而不是判断字符串里是否包含子串。这和C#里的string.Contains()完全不是一回事!
比如你写的 $_.DistinguishedName -contains 'world',只有当DistinguishedName是一个数组,且其中正好有一个元素等于'world'时才会返回$true,但实际上它是一个字符串,所以这个判断永远是$false——这就是你得不到结果的主要原因!
核心问题2:SID不是字符串类型
Get-ADComputer返回的对象里,SID是SecurityIdentifier对象,不是直接的字符串,直接用运算符判断会出问题,得先取它的.Value属性拿到字符串形式。
修正后的代码
把 -contains 换成字符串匹配的运算符,推荐用 -like(支持通配符)或者 -match(正则匹配),同时修正SID的取值:
Get-ADComputer -Filter * | Where-Object { $_.Enabled -and ($_.DistinguishedName -like '*world*' -or $_.DistinguishedName -like '*foo*') -and ($_.SID.Value -like '*bar*' -or $_.SID.Value -like '*something else*') }
如果想用更灵活的正则匹配,可以换成 -match:
Get-ADComputer -Filter * | Where-Object { $_.Enabled -and ($_.DistinguishedName -match 'world|foo') -and ($_.SID.Value -match 'bar|something else') }
额外优化:直接用AD Filter提升性能
其实没必要先拉取所有AD计算机再过滤,Get-ADComputer的-Filter参数可以直接在AD服务器端完成筛选,性能会好很多,尤其是AD里计算机数量多的时候:
Get-ADComputer -Filter { Enabled -eq $true -and (DistinguishedName -like '*world*' -or DistinguishedName -like '*foo*') -and (SID -like '*bar*' -or SID -like '*something else*') }
(AD Filter的语法和PowerShell略有不同,但这里的用法是兼容的,而且会自动处理SID的类型转换)
验证小技巧
你可以单独测试每个条件,比如随便拿一台符合条件的计算机对象,运行:
$computer = Get-ADComputer -Identity "某台计算机名" $computer.DistinguishedName -like '*world*' # 看看是否返回$true $computer.SID.Value -like '*bar*' # 确认SID的判断是否正确
这样能快速排查每个条件是否符合预期。
内容的提问来源于stack exchange,提问作者john

