在数组中查找字符串 Powershell V2.0

Find string in array Powershell V2.0

我在使用在 PowerShell V5.0 中运行但在 V2.0 中不起作用的脚本时遇到问题。

我需要比较两个 CSV 文件中的两列,并编辑一个 CSV 中的一个值(如果它存在于两个文件中)。

这是一个有问题的例子。 $a 在 V5.0 中重命名为 1X,在 V2.0 中它仍然是 1。我尝试使用 Compare 但这并没有解决我的问题。遗憾的是,无法在该特定机器上升级到 V5.0。如果您能提供任何建议,我们将不胜感激。

# create examples
$a = @()
$itema = New-Object PSObject
$itema | Add-Member -Type NoteProperty -Name 'ID' -Value '1'
$a += $itema

$b = @()
$itemb = New-Object PSObject
$itemb | Add-Member -Type NoteProperty -Name 'ID' -Value '1'
$b += $itemb

# problem
foreach ($value in $a) {
    $ID = $value.ID
    if ($b.ID -contains $ID) {$value.ID = $ID + "X"}
}

这是因为 Powershell 2.0 不支持允许您 select 数组中对象的多个同名属性的功能。

在更高版本的 Powershell 中,$b.ID 将为您提供一个包含 $b 中对象的所有 ID 值的数组。在 Powershell 2.0 中,这不会发生,$.ID$null,因为数组本身没有 ID 属性。

您可以像这样提取数组:

$known_IDs = $b | ForEach-Object { $_.ID }

之后,这在 PowerShell 2.0 中有效:

foreach ($item_a in $a) {
    if ($known_IDs -contains $item_a.ID) {
        $item_a.ID += "X"
    }
}

或者,作为管道:

$a | Where-Object { $known_IDs -contains $_.ID } | ForEach-Object { $_.ID += "X" } 

PowerShell v2 不支持 member enumeration,您在这里使用的是:

$b.ID -contains $ID

该功能是随 PowerShell v3 引入的。

在 PowerShell v2 中 $b.ID 尝试扩展 数组 $b 的 属性 ID,这会产生一个空的结果是因为数组对象没有这样的 属性.

在 PowerShell v3 和更高版本中 $b.ID 尝试在数组 $b 元素 上扩展 属性 ID (如果数组对象本身没有 属性)。

要使您的代码与 PowerShell v2 兼容,请更改:

if ($b.ID -contains $ID) {$value.ID = $ID + "X"}

进入这个:

if (@($b | Select-Object -Expand ID) -contains $ID) {$value.ID = $ID + "X"}

附录:

出于性能原因,在循环外仅扩展一次 ID 列表并将其存储在单独的变量中是有意义的

$id_list = @($b | Select-Object -Expand ID)

然后在比较中使用该变量:

if ($id_list -contains $ID) {$value.ID = $ID + "X"}

如果您确实 对性能有压力,我建议您根据 ID

创建哈希表
$id_list = @{}
foreach ($e in $b) {
    $id_list[$e.ID] = $true
}

然后像这样进行比较:

if ($id_list.ContainsKey($ID)) {$value.ID = $ID + "X"}

哈希表查找比 -contains 操作提供更好的性能,因为前者进行索引查找而后者对数组进行线性搜索。