gpt4 book ai didi

powershell - 递归函数行为不正确

转载 作者:行者123 更新时间:2023-12-02 23:40:19 26 4
gpt4 key购买 nike

我们在组成员的事件目录中具有以下结构:

BEL Test Top level
- BEL Test Sub level 1
- Bob
- BEL Test Sub level 1.1
- Jake
- Mike
- BEL Test Sub level 2
- BEL Test Sub level 2.1

所需的输出:
GroupName : BEL Test Top level
Member1 : BEL Test Sub level 1
Member2 : BEL Test Sub level 1.1
Member3 : Jake

GroupName : BEL Test Top level
Member1 : BEL Test Sub level 1
Member2 : BEL Test Sub level 1.1
Member3 : Mike

GroupName : BEL Test Top level
Member1 : BEL Test Sub level 1
Member2 : Bob

GroupName : BEL Test Top level
Member1 : BEL Test Sub level 2
Member2 : BEL Test Sub level 2.1

因此,对于每个最深的对象,都需要有一个 [PSCustomObject]作为输出。我不是递归函数方面的专家,但是我编写的以下代码非常接近:
$Name = 'BEL Test Top level'

$hash = $null

Function Add-MemberGroupHC {
Param (
[Parameter(Mandatory, ValueFromPipeline)]
$Identity,
$Past,
[Int]$Level
)

Begin {
if (-not $Level) {
$Level = 0
}

if (-not $Past) {
$Past = [Ordered]@{
GroupName = $Name
}
}

if ($Identity.GetType().Name -ne 'ADPrincipal') {
$Identity = Get-ADGroup -Identity $Identity
}
}

Process {
$Level++

Write-Verbose "Check members '$($Identity.Name)'"

$Members = Get-ADGroupMember $Identity

$Members | ForEach-Object {
Write-Verbose "Add property '$('Member' + $Level)' value '$($_.Name)'"
$Past.('Member' + $Level) = $_.Name

if (($_.ObjectClass -eq 'User') -or (-not (Get-ADGroupMember $_))) {
[PSCustomObject]$Past
}
$Past.('Member' + $Level) = $_.Name
[PSCustomObject]$Past
}

if ($_.ObjectClass -eq 'Group') {
Add-MemberGroupHC -Identity $_ -Past $Past -Level $Level
}
}

}
}

$Result = Add-MemberGroupHC $Name
$Result | fl *

在没有 child 的情况下调用自己时,它怎么可能只输出最深的层次?

最佳答案

我想采用自己的方法从一开始就了解它是如何工作的。我不能说这是否比您预期的方法更好或更差。希望您可以使用它来查看您可能出错的地方。

Function Get-HighestMemberKey{
param([hashtable]$HashTable)

# Collect all of the member# names. Find the highest one.
# If one does not exist null gets cast to 0 with [int]
return [int](($HashTable.GetEnumerator()) |
Select -ExpandProperty Name |
Where-Object{$_ -match "(\d+)$"} |
ForEach-Object{$Matches[0]} |
Measure-Object -Maximum |
Select -ExpandProperty Maximum)
}

function Get-ADMembersGroupChain{
param(
$GroupName,
$CurrentChain
)

$CurrentMembers = @(Get-ADGroupMember $GroupName)

# Check if this group has any members.
if($CurrentMembers.Count -gt 0){
# If there are any groups process them individually
$CurrentMembers | ForEach-Object{

if(!$CurrentChain){
# This is a root group. Start a new chain.
$CurrentChain = @{GroupName=$GroupName}
}

# Add this member to the chain.
# Create a new chain for this pass. Use clone to ensure we are working with a new chain.
$nextMemberIndex = (Get-HighestMemberKey $CurrentChain) + 1
$newChain = $CurrentChain.Clone()
$newChain."Member$nextMemberIndex" = $_.Name

# If this is a group continue the chain.
if($_.ObjectClass -eq "group"){
Get-ADMembersGroupChain -GroupName $_.SamAccountName -CurrentChain $newChain
} else {
# This is a user. Output the chain
[pscustomobject]$newChain
}
}
} else {
# The group is already part of the chain. Ouput as is.
[pscustomobject]$CurrentChain
}
}

$chains = Get-ADMembersGroupChain "BEL Test Top level"
$chains | ForEach-Object{$_| fl}

我们在这里所做的是构建以递归方式传递给函数的哈希表。当遇到一个组时,再次调用该函数。如果曾经有一个包含 0 个成员的组,或者如果找到一个用户,则到目前为止的链将转换为 psobject 并沿管道发送。

这样做有一个小的副作用,因为您无法保证成员显示的顺序。如果这是一个问题,您将看到为此构建自己的选择语句。

样本输出
GroupName : BEL Test Top level
Member3 : Jake
Member1 : BEL Test Sub level 1
Member2 : BEL Test Sub level 1.1

GroupName : BEL Test Top level
Member3 : Mike
Member1 : BEL Test Sub level 1
Member2 : BEL Test Sub level 1.1

GroupName : BEL Test Top level
Member1 : BEL Test Sub level 1
Member2 : Bob

GroupName : BEL Test Top level
Member1 : BEL Test Sub level 2
Member2 : BEL Test Sub level 2.1

不使用 Format-List ,就像您所做的那样,输出可能看起来不正确,因为 PowerShell 将根据管道中的第一个对象显示,但所有属性都将在那里。如果这是一个问题,那么您需要创建一个小函数来保证属性输出的顺序。一个基本的例子是:
function Order-Chain{
param(
$chain
)

# Take the group and members and ensure the are output in numerical order.
# Assume there is at least a property called GroupName
$properties = @("GroupName")
# Get all the remaining property names minus the first one.
$properties += $chain.psobject.properties.name | Where-Object{$_ -notin $properties} |
# Sort the property list on the number at the end of the property name
Sort-Object -Property {[void]($_ -match "\d+$");$matches[0]}

# Order the chain and send down the pipe
$chain | Select-Object $properties
}

这将创建一个排序的属性列表,该列表被馈送到 Select-Object。 .它可能看起来更智能/更易于使用 [ordered]创建哈希表时,但您无法克隆有序哈希,所以这就是我解决它的方法。

这里的所有功能都可以变得更加健壮,即使用 begin像你一样阻止,并进入高级功能,但现在可以正常运行。 当心 循环组,因为没有逻辑可以检测到这些。

关于powershell - 递归函数行为不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44158098/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com