如何使用 PSv2 在 PSobjects 数组中搜索特定对象键
How to search an array of PSobjects for a specific objects key using PSv2
我有一组对象。我想搜索数组以确定 $obj.NewName 中是否存在特定值。如果该值是唯一的,则将该值放入 $obj.NewName。如果确实存在,则增加值并再次搜索,直到该值是唯一的。
Function CreateObject ($origionalName)
{
$newName = $null
$obj = $null
$obj = New-Object PSObject
$obj | Add-Member -type NoteProperty -Name OrigionalName -Value $origionalName
$obj | Add-Member -type NoteProperty -Name NewName -Value $newName
Return ($obj)
}
Function Get-NewPatchName ($patch)
{
$patch.OrigionalPatchName.split("-") | Foreach {
## Pipelined string is $_. Check if it starts with "KB".
If ($_.substring(0,2) -like "kb" )
{
## This create the new name based on the substring containing "KB...", and adds the existing file extension.
$tempName = $_
## If there is a version number in the original file name, include that in the new name
If ($patch.OrigionalPatchName -like "*-v*")
{
$intPosition = ($patch.OrigionalPatchName.ToUpper()).IndexOf("-V")
$tempName += ($patch.OrigionalPatchName.substring($intPosition+1,2))
}
## Determine if name is unique
{
## STUCK HERE!!!!!!!!!!
}
}
}
}
$patchList = @()
$nameList = "AMD64-all-windows6.0-kb2900986-x64_63", `
"AMD64-all-windows6.0-kb3124275-x64_57", `
"AMD64-all-windows6.0-kb2900986-x64_63"
Foreach ($name in $nameList){
$patchList += CreateObject $name }
Foreach ($patch in $patchList) {
Get-NewPatchName $patch }
Foreach ($patch in $patchList) {
Write-Host "Origional Patch Name: " $patch.OrigionalName
Write-Host "New Patch Name : " $patch.NewName
}
预期结果:
Origional Patch Name: AMD64-all-windows6.0-kb2900986-x64_63
New Patch Name : kb2900986
Origional Patch Name: AMD64-all-windows6.0-kb3124275-x64_57
New Patch Name : kb3124275
Origional Patch Name: AMD64-all-windows6.0-kb2900986-x64_63
New Patch Name : kb2900986a
我会将 $origionalName 处理成 kb#,示例:
$tempName = "kb2900986"
然后我想看看$tempName 是否已经存在于任何$patch.newName 下的patchList 中。如果是这样,那么我会将 $tempName 增加到
$tempName = "kb2900986a"
和运行再次搜索。一旦 $tempName 是唯一的
$patch.newName = $tempName
我已经知道如何处理和递增 $tempName。我只是停留在如何搜索 $patchList 以确定 $tempName 当前是否存在任何 $patch.newName.
我假设您使用的是 PS 的较新版本,这个 不会 在 PS2 中工作,因为它使用shell 的较新版本的一个有点草率的功能,它使您正在处理的任务的生活变得更加轻松。下面的代码将进入您用评论标识的区域。
if($patchlist.newname -contains $tempname){
*do whatever you need to do if the list already contains the name*
} else {
*do whatever you need to do if the list doesn't contain the name*
}
这利用了 powershell 功能,该功能将自动访问 $patchlist
数组中每个项目的 .newname
属性 并将其显示为自己的数组我相信调用 $patchlist.newname
时的值是 PS3 中引入的一个有趣的数组功能。我还会通过传入补丁列表(最好使用不同的名称)来确保您的函数保持原子性,但这并不是真正必要的。
PS2版本
$templist = foreach($name in $patchlist){
$name.NewName
}
if($templist -contains $tempname){
*do whatever you need to do if the list already contains the name*
} else {
*do whatever you need to do if the list doesn't contain the name*
}
这适用于任何版本的 powershell,它没有完全优化(为每次迭代创建 $templist 数组)但它有效,如果您需要额外的速度,您可以根据需要进行更改
包含指向解决方案的重要指示。
这是一个惯用的 PowerShell v2+ 解决方案,它还简化了问题中的代码:
# Convert an array of patch names to custom objects containing
# an .OriginalName property with the input patch name, and a yet-to-be-assigned
# .NewName property.
Function CreateObjects ([string[]] $originalNames)
{
foreach ($name in $originalNames) {
[pscustomobject] @{ OriginalName = $name; NewName = $null }
}
}
# Assign a unique name to the .NewName property of all input objects.
Function Set-NewPatchNames ([pscustomobject[]] $patches)
{
# Initialize an aux. hashtable in which we'll keep track of the unique
# new names assigned so far.
$htNewNames = @{}
foreach ($patch in $patches) {
# Extract the KB number from the original name.
# Note: For brevity, the "-v" version-number extraction mentioned in the
# question is skipped.
$newNameCandidate = $patch.OriginalName -replace '.*-kb(\d+).*', ''
# Is the candidate for the new name unique?
if ($htNewNames.Contains($newNameCandidate)) { # Name already used.
# Find a unique variation of the name.
$rootName = $newNameCandidate
# Loop and append 'a', 'b', ... until a unique name is found.
# Note: With more than 26 duplicates, you'll run out of letters,
# at which point seemingly random Unicode chars. will be used.
$suffixCharCode = ([int] [char] 'a') - 1
do {
++$suffixCharCode
$newNameCandidate = $rootName + [char] $suffixCharCode
} while ($htNewNames.Contains($newNameCandidate))
}
# Assign the new name and record it in the hashtable of names used so far.
$patch.NewName = $newNameCandidate
$htNewNames.Add($newNameCandidate, $null)
}
}
# The input list of patch names.
$nameList = "AMD64-all-windows6.0-kb2900986-x64_63",
"AMD64-all-windows6.0-kb3124275-x64_57",
"AMD64-all-windows6.0-kb2900986-x64_63"
# Create a collection of custom objects with the original patch name
# stored in .OriginalName, and a yet-to-be-filled .NewName property.
$patchList = CreateObjects $nameList
# Fill the .NewName properties with unique names.
Set-NewPatchNames $patchList
# Output the resulting objects.
$patchList
在 PSv5.1 中,这会产生(代码 在 PSv2 中可以正常工作,但产生的可读性稍差的输出):
OriginalName NewName
------------ -------
AMD64-all-windows6.0-kb2900986-x64_63 2900986
AMD64-all-windows6.0-kb3124275-x64_57 3124275
AMD64-all-windows6.0-kb2900986-x64_63 2900986a
我有一组对象。我想搜索数组以确定 $obj.NewName 中是否存在特定值。如果该值是唯一的,则将该值放入 $obj.NewName。如果确实存在,则增加值并再次搜索,直到该值是唯一的。
Function CreateObject ($origionalName)
{
$newName = $null
$obj = $null
$obj = New-Object PSObject
$obj | Add-Member -type NoteProperty -Name OrigionalName -Value $origionalName
$obj | Add-Member -type NoteProperty -Name NewName -Value $newName
Return ($obj)
}
Function Get-NewPatchName ($patch)
{
$patch.OrigionalPatchName.split("-") | Foreach {
## Pipelined string is $_. Check if it starts with "KB".
If ($_.substring(0,2) -like "kb" )
{
## This create the new name based on the substring containing "KB...", and adds the existing file extension.
$tempName = $_
## If there is a version number in the original file name, include that in the new name
If ($patch.OrigionalPatchName -like "*-v*")
{
$intPosition = ($patch.OrigionalPatchName.ToUpper()).IndexOf("-V")
$tempName += ($patch.OrigionalPatchName.substring($intPosition+1,2))
}
## Determine if name is unique
{
## STUCK HERE!!!!!!!!!!
}
}
}
}
$patchList = @()
$nameList = "AMD64-all-windows6.0-kb2900986-x64_63", `
"AMD64-all-windows6.0-kb3124275-x64_57", `
"AMD64-all-windows6.0-kb2900986-x64_63"
Foreach ($name in $nameList){
$patchList += CreateObject $name }
Foreach ($patch in $patchList) {
Get-NewPatchName $patch }
Foreach ($patch in $patchList) {
Write-Host "Origional Patch Name: " $patch.OrigionalName
Write-Host "New Patch Name : " $patch.NewName
}
预期结果:
Origional Patch Name: AMD64-all-windows6.0-kb2900986-x64_63
New Patch Name : kb2900986
Origional Patch Name: AMD64-all-windows6.0-kb3124275-x64_57
New Patch Name : kb3124275
Origional Patch Name: AMD64-all-windows6.0-kb2900986-x64_63
New Patch Name : kb2900986a
我会将 $origionalName 处理成 kb#,示例:
$tempName = "kb2900986"
然后我想看看$tempName 是否已经存在于任何$patch.newName 下的patchList 中。如果是这样,那么我会将 $tempName 增加到
$tempName = "kb2900986a"
和运行再次搜索。一旦 $tempName 是唯一的
$patch.newName = $tempName
我已经知道如何处理和递增 $tempName。我只是停留在如何搜索 $patchList 以确定 $tempName 当前是否存在任何 $patch.newName.
我假设您使用的是 PS 的较新版本,这个 不会 在 PS2 中工作,因为它使用shell 的较新版本的一个有点草率的功能,它使您正在处理的任务的生活变得更加轻松。下面的代码将进入您用评论标识的区域。
if($patchlist.newname -contains $tempname){
*do whatever you need to do if the list already contains the name*
} else {
*do whatever you need to do if the list doesn't contain the name*
}
这利用了 powershell 功能,该功能将自动访问 $patchlist
数组中每个项目的 .newname
属性 并将其显示为自己的数组我相信调用 $patchlist.newname
时的值是 PS3 中引入的一个有趣的数组功能。我还会通过传入补丁列表(最好使用不同的名称)来确保您的函数保持原子性,但这并不是真正必要的。
PS2版本
$templist = foreach($name in $patchlist){
$name.NewName
}
if($templist -contains $tempname){
*do whatever you need to do if the list already contains the name*
} else {
*do whatever you need to do if the list doesn't contain the name*
}
这适用于任何版本的 powershell,它没有完全优化(为每次迭代创建 $templist 数组)但它有效,如果您需要额外的速度,您可以根据需要进行更改
这是一个惯用的 PowerShell v2+ 解决方案,它还简化了问题中的代码:
# Convert an array of patch names to custom objects containing
# an .OriginalName property with the input patch name, and a yet-to-be-assigned
# .NewName property.
Function CreateObjects ([string[]] $originalNames)
{
foreach ($name in $originalNames) {
[pscustomobject] @{ OriginalName = $name; NewName = $null }
}
}
# Assign a unique name to the .NewName property of all input objects.
Function Set-NewPatchNames ([pscustomobject[]] $patches)
{
# Initialize an aux. hashtable in which we'll keep track of the unique
# new names assigned so far.
$htNewNames = @{}
foreach ($patch in $patches) {
# Extract the KB number from the original name.
# Note: For brevity, the "-v" version-number extraction mentioned in the
# question is skipped.
$newNameCandidate = $patch.OriginalName -replace '.*-kb(\d+).*', ''
# Is the candidate for the new name unique?
if ($htNewNames.Contains($newNameCandidate)) { # Name already used.
# Find a unique variation of the name.
$rootName = $newNameCandidate
# Loop and append 'a', 'b', ... until a unique name is found.
# Note: With more than 26 duplicates, you'll run out of letters,
# at which point seemingly random Unicode chars. will be used.
$suffixCharCode = ([int] [char] 'a') - 1
do {
++$suffixCharCode
$newNameCandidate = $rootName + [char] $suffixCharCode
} while ($htNewNames.Contains($newNameCandidate))
}
# Assign the new name and record it in the hashtable of names used so far.
$patch.NewName = $newNameCandidate
$htNewNames.Add($newNameCandidate, $null)
}
}
# The input list of patch names.
$nameList = "AMD64-all-windows6.0-kb2900986-x64_63",
"AMD64-all-windows6.0-kb3124275-x64_57",
"AMD64-all-windows6.0-kb2900986-x64_63"
# Create a collection of custom objects with the original patch name
# stored in .OriginalName, and a yet-to-be-filled .NewName property.
$patchList = CreateObjects $nameList
# Fill the .NewName properties with unique names.
Set-NewPatchNames $patchList
# Output the resulting objects.
$patchList
在 PSv5.1 中,这会产生(代码 在 PSv2 中可以正常工作,但产生的可读性稍差的输出):
OriginalName NewName
------------ -------
AMD64-all-windows6.0-kb2900986-x64_63 2900986
AMD64-all-windows6.0-kb3124275-x64_57 3124275
AMD64-all-windows6.0-kb2900986-x64_63 2900986a