Назад | Перейти на главную страницу

Массивы Powershell и сравнения

По профессии я системный администратор Linux, но мне нужно немного потрудиться. Моя проблема в следующем:

Я получаю список активных пользователей из 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 символа: 24 + echo $ allusers.contains <<<< ("joeq") + CategoryInfo: InvalidOperation: (содержит: 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 кажется немного избыточным TBH (по крайней мере, он был бы в bash!) Ну что ж! спасибо за ваш вклад всем.

Проблема связана с вашей форматной таблицей :)

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

Имя типа: Microsoft.PowerShell.Commands.Internal.Format.FormatStartData

Имя MemberType Определение ---- ---------- ---------- Equals Method bool Equals (System.Object obj) GetHashCode
Метод int GetHashCode () GetType
Тип метода GetType () ToString
Строка метода ToString () autosizeInfo
Свойство Microsoft.PowerShell.Commands.Internal.Format.AutosizeInfo, Syste ... ClassId2e4f51ef21dd47e99d3c952918aff9cd Строка свойства ClassId2e4f51ef21dd47e99d3c952918aff9cd {get;} groupingEntry
Свойство
Microsoft.PowerShell.Commands.Internal.Format.GroupingEntry, Syst ... Свойство pageFooterEntry
Microsoft.PowerShell.Commands.Internal.Format.PageFooterEntry, Sy ... Свойство pageHeaderEntry
Microsoft.PowerShell.Commands.Internal.Format.PageHeaderEntry, Sy ... Свойство shapeInfo
Microsoft.PowerShell.Commands.Internal.Format.ShapeInfo, System.M ...

Это не то, что вы хотите искать по имени пользователя.

Если ты сделаешь это

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

Вы получите коллекцию объектов со всеми вашими свойствами. И здесь вы можете проверить, если так

$allusers.SamAccountName -eq "joeq"

Теперь вы можете продолжить сценарий и зациклить список всех пользователей, попробуйте следующее:

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

Вы можете использовать "select -expand xxx" для создания плоского (?) Массива, в котором вам не нужно использовать имя свойства для анализа массива.

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

Если вам не нужно использовать $allusers как набор пользовательских объектов несколько раз (или, если все, что вам нужно, это имена пользователей), вы можете сократить объем того, что храните в памяти оболочки, сделав следующее:

$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")

Вернет логический результат этой проверки.

Однако этот последний метод не совсем оптимален, если вы пишете сценарий или функцию, которые кому-то другому может понадобиться разобрать, чтобы исправить или перепрофилировать в ваше отсутствие. Если это только для вас, и все, что вам нужно, это один логический результат, я бы пошел с ним, он должен работать примерно столько же времени, и вы не будете держаться за этот (потенциально) огромный массив имен пользователей (или даже больший массив объектов И массив имен пользователей). Опять же, если вы повторно используете этот массив пользовательских объектов, ваш путь должен быть в порядке.

Подсчет через массив с ($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"

Если при выборе выбирается свойство или свойства для сохранения, а параметр раскрытия сводит это свойство к простой строке вместо того, чтобы сохранять его как пару имя / значение.

[Это соответствует тому же ответу, что и Craig620, но я отвечаю против цикла подсчета, поэтому путь к ответу другой].