Powershell 数组和比较

Powershell 数组和比较

我是一名专业的 Linux 系统管理员,但必须进行一些 powershell 操作。我的问题是:

我使用以下命令从 AD 获取活跃用户列表:

$allusers= get-aduser -Filter {Enabled -eq $true} | FT samAccountName 

我的意图是让 $allusers 变成一个填充有 get-aduser 命令输出行的数组。在数组填充之后立即弹出这个块似乎可以证实情况确实如此。

for ($i; $i -le $allusers.length; $i++) {
    $allusers[$i]
}

太棒了!现在我想检查给定的用户名是否存在于该数组中。我看到数组包含一个非常方便的“Contains()”函数,看起来它应该可以满足我的目的。

echo $allusers.Contains("joeq")

但可惜!我收到此错误:

Method invocation failed because [System.Object[]] doesn't contain a method named 'contains'.

在 C:\Users\dylanh\jirauserpurge.ps1:33 char:24 + echo $allusers.contains <<<< ("joeq") + CategoryInfo : InvalidOperation: (contains:String) [], RuntimeException + FullyQualifiedErrorId : MethodNotFound

嗯...好吧,我们去“老派”吧

for ($i; $i -le $allusers.length; $i++) {
    if ($allusers[$i] -eq "joeq") {
        echo "joeq present"
    }
}

条件永远不匹配!我的脑袋疼!好吧,这里可能有一些空格字符造成了麻烦,让我们修剪一下:

for ($i; $i -le $allusers.length; $i++) {
    if ($allusers[$i].Trim() -eq "joeq") {
        echo "joeq present"
    }
}

但事实并非如此,结果是这样的:

Method invocation failed because [Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData] doesn't contain a method named 'Trim'.
At C:\Users\dylanh\jirauserpurge.ps1:39 char:24
+     if ($allusers[$i].Trim <<<< () -eq "nickf") {
+ CategoryInfo          : InvalidOperation: (Trim:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound

显然,我忽略了某种类型转换问题。我需要做什么才能在“数组”中搜索特定值?

更新:在 fdibot 的回答和 HopelessN00b 的评论的帮助下,我找到了一个可行的解决方案:

$allusers= get-aduser -Filter {Enabled -eq $true}
$usernames = @()
for ($i=0; $i -le $allusers.length; $i++) {
    $usernames += $allusers[$i].SamAccountName
}
$usernames -contains "joeq"

老实说,额外的 for 循环似乎有点多余(或者至少在 bash 中是这样的!)好吧!感谢大家的意见。

答案1

问题出在你的 Format-Table 上:)

$allusers= get-aduser -Filter {Enabled -eq $true} | FT samAccountName
$allusers |  gm

类型名称:Microsoft.PowerShell.Commands.Internal.Format.FormatStartData

名称 MemberType 定义 ---- ---------- ---------- Equals 方法 bool Equals(System.Object obj) GetHashCode
方法 int GetHashCode() GetType
方法 type GetType() ToString
方法 string ToString() autosizeInfo
属性 Microsoft.PowerShell.Commands.Internal.Format.AutosizeInfo,系统... ClassId2e4f51ef21dd47e99d3c952918aff9cd 属性 string ClassId2e4f51ef21dd47e99d3c952918aff9cd {get;} groupingEntry
属性
Microsoft.PowerShell.Commands.Internal.Format.GroupingEntry,系统... pageFooterEntry 属性
Microsoft.PowerShell.Commands.Internal.Format.PageFooterEntry,系统... pageHeaderEntry 属性
Microsoft.PowerShell.Commands.Internal.Format.PageHeaderEntry,系统... shapeInfo 属性
Microsoft.PowerShell.命令.内部格式.ShapeInfo,系统.M...

这并不是您想要搜索的用户名。

如果你这样做

$allusers= get-aduser -Filter {Enabled -eq $true}
$allusers | gm

您将获得一个包含所有属性的对象集合。在这里,您可以使用 if 进行检查,如下所示

$allusers.SamAccountName -eq "joeq"

现在您可以继续您的脚本,并循环所有用户列表,请尝试以下操作:

get-aduser -Filter {Enabled -eq $true} | Foreach {
  if ($_.SamAccountName -eq "something") { "OK" }
}

答案2

您可以使用“select -expand xxx”来生成扁平化(?)数组,其中您不需要使用属性名称来解析数组。

$allusers = get-aduser -Filter {Enabled -eq $true} | select -expand samAccountName
PS C:\> $allusers.contains("GeoSword")
True

答案3

如果你不需要$allusers多次使用用户对象的集合(或者你需要的只是用户的名称),你可以通过执行以下操作来减少在 shell 内存中存储的内容:

$usernames = (get-aduser -Filter {Enabled -eq $true}).samAccountName
$usernames.Contains("check_value")

或者说你有一个想要循环命名的检查值的完整数组$check_array,并且想要检查每个用户名以查看它们是否在该数组中:

$usernames = (get-aduser -Filter {Enabled -eq $true}).samAccountName
foreach ($i in $check_array) {
    $usernames.Contains($i)
}

但是,根据两个数组的相对长度,第二个数组可能会更好:

foreach ($j in (get-aduser -Filter {Enabled -eq $true}).samAccountName) {
    $check_array.Contains($j)
}

最后,如果您不需要在此步骤之后重复使用用户名列表,而只需要检查一个检查值:

((get-aduser -Filter {Enabled -eq $true}).samAccountName).Contains("check_value")

将返回该检查的布尔结果。

但是,如果您编写的脚本或函数可能需要其他人在您不在的情况下拆开进行修复或重新利用,那么最后一种方法并不完全是最佳实践。但是,如果这仅供您使用,并且您需要的只是一个布尔结果,那么我会选择那个,它应该运行大约相同的时间,并且您不会保留(可能)巨大的用户名数组(甚至更大的对象数组和用户名数组)。不过,如果您要重用该用户对象数组,那么您的方法应该没问题。

答案4

使用 来计数数组($i=0; $i ...可能会更简洁 - PowerShell 使用 可以很好地遍历所有内容foreach,但通常您也不需要这样做。您的最终代码:

$allusers= get-aduser -Filter {Enabled -eq $true}
$usernames = @()
for ($i=0; $i -le $allusers.length; $i++) {
    $usernames += $allusers[$i].SamAccountName
}
$usernames -contains "joeq"

可能:

$usernames = Get-ADUser -Filter {Enabled -eq $true} | select -Expand sAmAccountName
$usernames -contains "joeq"

其中 select 选择要保留的一个或多个属性,而 expand 参数将这一属性展平为纯字符串,而不是将其保留为名称/值对。

[这与 Craig620 的答案相同,但我的回答违反了计数 for 循环,因此答案的路径不同]。

相关内容