string - 两个不同大小的对象和 $null

标签 string powershell pipeline enumeration

下面的代码适用于每个实例,除非一个对象是 $null 并且另一个对象有一项。当这种情况发生时,输出会变成 1 个字母,就像索引一样,我不知道为什么。 如何组合这两个对象来生成最终报告?

$ADGroups = Get-ADPrincipalGroupMembership -Identity $UserSam | Select-Object distinguishedName, name | Where-Object { ($_.distinguishedName -ne 'CN=Domain Users,CN=Users,DC=com') }

#record AD groups
$ADResult = @()
if ($null -eq $ADGroups) {
    Write-Warning "No AD Groups"
    $ADResult = [PSCustomObject]@{ 
        ADGroups                  = @()
        ADGroupsdistinguishedName = @()
    }
}
Else {
    $ADResult = $ADGroups | ForEach-Object {
        [PSCustomObject]@{
            ADGroups                  = $_.name
            ADGroupsdistinguishedName = $_.distinguishedName
        }
    }
}

#============= Now Google, get user groups and record
$GoogleGroups = gam print groups member $email members managers owners | ConvertFrom-Csv

# Record Google Groups
$GResult = @()
If ($null -eq $GoogleGroups) {
    Write-Warning "No Google Groups"
    $GResult = [PSCustomObject]@{
        GoogleGroups = @()
        Role         = @()
    }
}
Else {
    $group = $null
    $GResult = ForEach ($group in $GoogleGroups) {
        #this records what role the user had in the group(s)
        $GoogleMember = gam print group-members group $group.email members | ConvertFrom-Csv | Select-Object -ExpandProperty email
        $Role = $null
        If ( $GoogleMember -contains $EMAIL) {
            $Role = 'Member'
        }
        Else {
            $GoogleManager = gam print group-members group $group.email managers | ConvertFrom-Csv | Select-Object -ExpandProperty email
            If ($GoogleManager -contains $EMAIL) {
                $Role = 'Manager'
            }
            Else {
                $Role = 'Owner'
            }
        }
        [PSCustomObject]@{
            GoogleGroups = $group.email
            Role         = $role
        }
        $group = $null
    }
}

# ---------now report that will be dropped off at end
[int]$max = $ADResult.count
if ([int]$GResult.count -gt $max) { [int]$max = $GResult.count }

If ($max -eq 1 -or $max -eq 0) {
    $Result = [PSCustomObject]@{ 
        PrimaryEmail                 = $email
        Title                        = $UserInfo.title
        Department                   = $UserInfo.Department
        Manager                      = $Manager
        ADGroupName                  = $ADResult.ADGroups
        ADGroupNameDistinguishedName = $ADResult.ADGroupsdistinguishedName
        GoogleGroup                  = $GResult.GoogleGroups
        Role                         = $GResult.role
        DateOfSeparation             = (Get-Date).ToString("yyyy_MM_dd")
        UserDistinguishedName        = $UserInfo.distinguishedName
        UserOU                       = $UserInfo.Ou
        PrimaryGroup                 = $UserInfo.primaryGroup.Split('=').Split(',')
    }
}
Else {
    $Result = for ( $i = 0; $i -lt $max; $i++) {
        [PSCustomObject]@{ 
            PrimaryEmail                 = $email
            Title                        = $UserInfo.title
            Department                   = $UserInfo.Department
            ADGroupName                  = $ADResult.ADGroups[$i]
            ADGroupNameDistinguishedName = $ADResult.ADGroupsdistinguishedName[$i]
            GoogleGroup                  = $GResult.GoogleGroups[$i]
            Role                         = $GResult.role[$i]
            DateOfSeparation             = (Get-Date).ToString("yyyy_MM_dd")
            UserDistinguishedName        = $UserInfo.distinguishedName
            UserOU                       = $UserInfo.Ou
            PrimaryGroup                 = $UserInfo.primaryGroup.Split('=').Split(',')[$i]
        }
    }
}


$Result | Export-Csv 'C:\temp\Groups.csv' -NoTypeInformation

最佳答案

根据问题的抽象描述:

您在 PowerShell 中看到不幸的不对称:

  • 管道中,[string] 实例被视为单个对象

    PS> ('foo' | Measure-Object).Count
    1
    
  • 索引而言,它被视为字符数组

    PS> 'foo'[0]
    f
    

捕获 PowerShell 管道输出的一般特征是,如果命令在特定情况仅输出单个对象,该对象按原样捕获,而两个或多个输出对象会生成类型为 [object[]] 的常规 PowerShell 数组。

  • 通常,这不是问题,因为 PowerShell 对标量和集合的统一处理允许您甚至可以索引到标量(单个对象),即隐式地将单个对象视为单元素数组:

    PS> (Write-Output 42, 43)[0]
    42
    
    PS> (Write-Output 42)[0]
    42  # still OK, even though only *one* object was output; same as: (42)[0]
    
  • 但是,使用单个 [string] 实例作为输出就会出现问题,原因如上所述:

    PS> (Write-Output 'foo', 'bar')[0]
    foo # OK
    
    PS> (Write-Output 'foo')[0]
    f   # !! Indexing into a *single string* treats it as *character array*
    

同样适用于通过 member-access enumeration perhaps surprisingly 返回的值:

PS> (Get-Item $HOME, /).FullName[0]
C:\Users\Jdoe

PS> (Get-Item $HOME).FullName[0]
C # !! Indexing into a *single string* treats it as *character array*

解决方法:

  • 将感兴趣的命令括在 @(...)array-subexpression operator 中,以确保其输出始终被视为数组。

    PS> @(Write-Output 'foo')[0]
    foo # OK
    
  • 或者,在变量中捕获命令的输出时,将该变量的类型限制为 [array](与 [object[]] 相同)或强类型数组 [string[]] :

    PS> [array] $output = Write-Output 'foo'; $output[0]
    foo # OK
    

关于string - 两个不同大小的对象和 $null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69111301/

相关文章:

azure - 如何使用 azure 管道变量为我的 docker 镜像设置环境变量?

在 PHP 生成的 JavaScript 中调用时,通过 heredoc 声明的 PHP 变量将无法正确解析

powershell - 设置系统有权通过Powershell写入文件夹

internet-explorer - 使用 Powershell 终止所有运行时间超过 5 分钟的 Internet Explorer 进程

html - 如何将自定义字体添加到 ConvertTo-HTML 的 <head> 部分?

linux - cat 和 ls 命令的流水线化

linux - 在 bash 中评估代表单个管道命令的两个变量的最佳方法是什么?

Java将从数据库返回的日期值拆分为单独的日期和时间字符串

r - R中使用CamelCase分隔字符串中的标题和副标题

创建字符串链表