首页 > 解决方案 > 在数组中查找字符串 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"}
}

标签: powershellpowershell-2.0powershell-5.0

解决方案


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

$b.ID -contains $ID

该功能是在 PowerShell v3 中引入的。

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

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

要使您的代码与 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"}

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


推荐阅读