1

如果我错过了社交规范,请先在 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。所以它正在删除正确数量的对象,而不是预期的对象。我在这里做错了什么?由于我正在从我正在比较的确切数组中提取数据,因此我想不出任何其他标准,它将搜索会返回意外匹配的任何其他标准。我还尝试在比较之前按相同的属性对每个数组进行排序,因为我正在掌握但正如预期的那样并没有解决它。

提前致谢!

4

5 回答 5

2

简单的方法是执行相同的-like赋值,但使用相反的运算符,-notlike例如:

$Array2 = $Array1 | where-object Username -like 'a*'
$Array3 = $Array1 | where-object Username -notlike 'a*'

笔记:

(不确定是否是匹配问题中的拼写错误:)'*\a*',匹配应在“ ”字符a*后仅包含一个星号。a您想匹配以“ ”和“ ”开头的所有内容以匹配之后的任何内容(例如,只匹配“Alex”,而不是“Brad”)。a*

于 2020-04-23T17:19:04.630 回答
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 <=
于 2020-04-23T17:22:12.480 回答
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')
于 2020-04-23T17:23:48.960 回答
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           <=  
于 2020-04-23T17:38:34.263 回答
0

我的结论是,一些命令行开关以破坏比较对象的方式构建数组。我仍然不确定这种神秘的“方式”是什么,但问题在使用 Citrix 的 Get-BrokerSession 时会出现,而在使用 Get-AdUser 时不会出现。

长答案对于那些真正想要使用 compare-object 的人来说,这是我让它工作的方式:

compare-object $Array1 $Array2 -Property Username -PassThru

-PassThru 对我来说是灵光乍现的时刻。

我的问题特别是关于 compare-object 如何/为什么没有按我预期的方式工作。根据我的解释,所有答案只提供了解决问题的不同方法,并没有真正回答问题。特别感谢 @js2010 继续与我合作。

于 2020-04-24T23:51:34.633 回答