比较对象返回无效结果

时间:2020-04-23 16:47:42

标签: arrays powershell compare compareobject

第一篇关于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。因此,它正在删除正确数量的对象,而不是预期的对象。我在这里做错了什么?由于我正在从要比较的确切数组中提取数据,因此我想不出其他任何条件,因此搜索该条件将返回意外的匹配。在比较之前,我还尝试按相同的属性对每个数组进行排序,因为我已经掌握了,但是按预期无法解决问题。

谢谢!

5 个答案:

答案 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继续与我合作。

相关问题