在数组中查找字符串 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
操作提供更好的性能,因为前者进行索引查找而后者对数组进行线性搜索。
我在使用在 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
操作提供更好的性能,因为前者进行索引查找而后者对数组进行线性搜索。