powershell 检查值列表是否与其他列表中的值相同

tp5buhyn  于 2023-01-30  发布在  Shell
关注(0)|答案(4)|浏览(195)

我解析了一个文本文件的值,并将各个值收集到一个列表中。如果有足够的字节,则将列表以Intel-HEX格式发送到输出。我希望隐藏所有值都为0xFF的行。
为此,我定义了一个列表$emptyline,并用所需的模式填充它。

$empty = (0xFF, 0xFF, 0xFF, 0xFF)
$values = (0xFF, 0xFF, 0xFF, 0xFF)

$values.Equals($empty)

令人惊讶的是,最后一个表达式的结果为False。我如何检查所有值为0xFF的行?

rqqzpn5f

rqqzpn5f1#

    • TL;医生**
      • 正确的数组比较:**
$empty = (0xFF, 0xFF, 0xFF, 0xFF)
$values = (0xFF, 0xFF, 0xFF, 0xFF)

# -> $true
([Collections.IStructuralEquatable] $values).Equals(
  $empty,
  [Collections.Generic.EqualityComparer[int]]::Default
)

有关说明,请参见下一节。

      • 通过 * string * comparison**的实用快捷方式,它假设数组元素的字符串化是有意义的和明确的(这里的情况就是这样):
# -> $true, i.e. the values are equal
"$values" -eq "$empty"

这依赖于PowerShell的内置数组(集合)字符串化,它用空格连接(字符串化)元素(例如,"$(1, 2)"-〉"1 2"

      • 在 * 单个 * 数组中查找非0xFF值**:
# -> $true, i.e. all values are 0xFF
($values -ne 0xFF).Count -eq 0

这依赖于PowerShell的比较运算符,如-eq及其求反形式-ne,如果它们的LHS是一个数组(集合),则充当 * 过滤器 ,即它们返回一个(新的) 匹配值的子数组 *。
至于你所尝试的
$values.Equals($empty)
令人惊讶的是,最后一个表达式的结果为False
您的.Equals调用调用bool Equals(System.Object obj)方法重载,它测试 * 引用相等 *,这意味着只有当操作数引用 * 完全相同的数组示例 * 时,才返回$true;例如:

# !! $false, because the two arrays - despite having the same(-valued) elements -
# !! are *different array instances*.
@(1, 2).Equals(@(1, 2))

但是,* 有 * 一个.Equals()重载可以做您想要做的事情,即System.Collections.IStructuralEquatable接口提供的重载,它有 * 两个 * 参数:
x1米11米1x
如上所示,在实现System.Collections.IEqualityComparer接口的默认System.Collections.Generic.EqualityComparer<T>示例的帮助下,使用该重载执行所需的逐个元素比较。

    • 替代方法是使用Compare-Object**cmdlet,它非常灵活,还允许您在需要时标识两个数组之间的 * 特定差异 *:
$empty = (0xFF, 0xFF, 0xFF, 0xFF)
$values = (0xFF, 0xFF, 0xFF, 0xFF)

# -> $true
-not (Compare-Object -SyncWindow 0 $empty $values | Select-Object -First 1)
  • 默认情况下,Compare-Object只返回输入数组(集合)之间存在 * 差异 * 的元素,因此任何输出的存在都意味着至少找到了一个差异。
  • -not隐式地将输出视为[bool],根据PowerShell的隐式布尔强制规则(参见this answer的底部),这意味着 * no * 输出将生成$false,而[pscustomobject]作为Compare-Object的输出将生成$true
  • -SyncWindow 0| Select-Object -First 1是 * 优化 *(对于 * 小 * 数组可能不需要):
  • -SyncWindow 0确保仅比较直接对应的元素;默认情况下,元素的顺序并不重要。2这样可以更快地进行比较。
  • 一旦Compare-Object找到 * 第一个 * 差异(如果有),Select-Object -First 1就停止处理。
kcwpcxri

kcwpcxri2#

我想取消所有值都是0xFF的行。
如果你想检查是否所有的项都是0xFF,那么你可以遍历它们并寻找任何不是0xFF的值。

# make some test data - a million 0xff
$x = @(0xff) * 1000000;

$valid = $true;
foreach( $i in $x )
{
    if( $i -ne 0xFF )
    {
        $valid = $false;
        break;
    }
}

write-host $valid;
# True

在我的机器上,这大约需要400ms,但一旦发现非0xFF,就会失败,因此无效数据会更快:

# make some test data - a 0x00 followed by a million 0xff
$x = @(0x00) + (@(0xff) * 1000000);

大约需要3.5ms。

frebpwbc

frebpwbc3#

为了用另一种替代方法来补充这些有用的答案,Linq提供了SequenceEqual,用于两个集合的相等性比较:

$empty = 0xFF, 0xFF, 0xFF, 0xFF
$values = 0xFF, 0xFF, 0xFF, 0xFF
[System.Linq.Enumerable]::SequenceEqual([int[]] $empty, [int[]] $values)
u5i3ibmn

u5i3ibmn4#

不如这样:
PSObject.比较(对象)方法
https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.psobject.compareto?view=powershellsdk-7.3.0

$empty  = (0xFF, 0xFF, 0xFF, 0xFF)
$values = (0xFF, 0xFF, 0xFF, 0xFF)

("$empty").CompareTo("$values")
# Results
<#
0
#>

$empty  = (0xFF, 0xFF, 0xFF, 0xFF)
$values = (0xFF, 0xFF, 0xFF, 0xFFF)

("$empty").CompareTo("$values")
# Results
<#
-1
#>

相关问题