第一篇关于stackoverflow的帖子,如果我错过了一项社会规范,请提前道歉。
我在PowerShell中有一个数组,其中包含数千个对象。每个对象具有属性(例如用户名,登录时间,他们登录的计算机等)的标准材料。然后,我用名称以A开头的用户从第一个数组中分离出少量对象。
$Array2 = $Array1 | where-object Username -like '*\a*'
这按预期工作。
我想构建一个仅包含$ Array1中不在$ Array2中的对象的第三个数组。换句话说,只有用户名不以A开头的用户组成的数组。 这似乎是要走的路:
$Array3 = compare-object $Array1 $Array2 | select-object -expandproperty InputObject
期望:
$Array3 | where-object Username -like '*\a*'
返回无结果
我得到的是很多结果。奇怪的是,如果我查看每个数组的.count,则数学计算出结果。 Array1减去Array2等于Array3。因此,它正在删除正确数量的对象,而不是预期的对象。我在这里做错了什么?由于我正在从要比较的确切数组中提取数据,因此我想不出其他任何条件,因此搜索该条件将返回意外的匹配。在比较之前,我还尝试按相同的属性对每个数组进行排序,因为我已经掌握了,但是按预期无法解决问题。
谢谢!
答案 0 :(得分:2)
简单的方法是执行相同的-like
分配,但使用相反的运算符-notlike
,例如:
$Array2 = $Array1 | where-object Username -like 'a*'
$Array3 = $Array1 | where-object Username -notlike 'a*'
注意:
(不确定匹配项'*\a*'
中是否有错字),匹配项应为a*
,并且在“ a
”字符后仅带有一个星号。您想将开始的所有内容都用“ a
”和“ *
”进行匹配(例如,仅匹配“ Alex”,而不匹配“ Brad”)。
答案 1 :(得分:2)
比较对象以一种有趣的方式工作。对于对象,通常需要指定属性。我很惊讶文档没有这样的例子。不幸的是,-property不能使用通配符。我认为如果没有“ -property”,除非有特殊的compareto()或equals()方法,否则它将比较对象的字符串版本。我认为使用get-aduser输出,它将比较字符串(可分辨名称的)。
$a = @([pscustomobject]@{name='joe'})
$b = @([pscustomobject]@{name='joey'})
compare-object $a $b # no output, they're equal!
compare-object $a $b -property name
name SideIndicator
---- -------------
joey =>
joe <=
尝试日期时间。它使用字符串以外的东西进行比较。
$a = get-date; sleep -Milli 500; $b = get-date
$a.tostring(); $b.tostring()
4/23/2020 6:33:56 PM
4/23/2020 6:33:56 PM
$a -eq $b
False
compare-object $a $b
InputObject SideIndicator
----------- -------------
4/23/2020 6:33:56 PM =>
4/23/2020 6:33:56 PM <=
答案 2 :(得分:2)
您可以通过取反Where-Object
操作数(-notlike
而不是-like
)来解决此问题:
$Array2 = $Array1 |Where-Object Username -like *\a*
$Array3 = $Array1 |Where-Object Username -notlike *\a*
...,或者,您可以利用.Where()
扩展方法的“拆分”模式,并在一次分配中完成它:
$Array2,$Array3 = $Array1.Where({$_.Username -like '*\a*'}, 'Split')
答案 3 :(得分:0)
我认为Compare-Object
内部使用ToString()
方法比较对象。
class foo {
[string]$str
foo($str) {
$this.str = $str
}
}
class bar {
[string]$str
bar($str) {
$this.str = $str
}
[string] ToString() { return $this.str }
}
"== Compare foo object =="
$fooA = [foo]::new("a")
$fooB = [foo]::new("b")
compare $fooA $fooB -IncludeEqual | ft
"== Compare bar object =="
$barA = [bar]::new("a")
$barB = [bar]::new("b")
compare $barA $barB -IncludeEqual | ft
输出:
== Compare foo object ==
InputObject SideIndicator
----------- -------------
foo ==
== Compare bar object ==
InputObject SideIndicator
----------- -------------
b =>
a <=
答案 4 :(得分:0)
我的结论是,某些Commandlet以破坏比较对象的方式构建数组。我仍然不确定这个神秘的“方式”是什么,但是使用Citrix的Get-BrokerSession时会出现此问题,而使用Get-AdUser时不会出现此问题。
长答案 对于那些真正想要使用比较对象的人,这是我使其工作的方式:
compare-object $Array1 $Array2 -Property Username -PassThru
-PassThru是我的尤里卡时刻。
我的问题特别是关于比较对象为何/为什么没有按我预期的方式工作。根据我的解释,所有答案仅提供解决问题的不同方法,而实际上并未回答问题。特别感谢@ js2010继续与我合作。