Цикл foreach powershell: Управление потоком — PowerShell | Microsoft Learn
Содержание
Управление потоком — PowerShell | Microsoft Learn
-
Статья -
-
Написание сценариев
Когда вы переходите от написания однострочных элементов кода PowerShell к написанию сценариев, это может показаться намного сложнее, чем есть на самом деле. Сценарий — это всего лишь те же или похожие команды, которые вы можете запускать в интерактивном режиме в консоли PowerShell, если они не сохранены в виде файла .PS1
. Существуют некоторые конструкции написания сценариев, которые вы можете использовать вместо командлета ForEach-Object
, например цикл foreach
. Эти различия могут ввести в заблуждение начинающих пользователей, особенно если они полагают, что foreach
является конструкцией сценария и псевдонимом для командлета ForEach-Object
.
Выполнение цикла
Одно из основных преимуществ PowerShell состоит в следующем: если вы определили способ выполнения задачи для одного элемента, вы можете так же легко выполнить ее для нескольких сотен элементов. Достаточно пройтись в цикле по этим элементам, используя один из множества различных типов циклов в PowerShell.
ForEach-Object
ForEach-Object
— это командлет для прохода по элементам в конвейере, например с помощью однострочных элементов кода PowerShell. ForEach-Object
осуществляет потоковую передачу объектов по конвейеру.
Хотя параметр Module для Get-Command
принимает несколько значений в виде строк, он осуществляет это только через входные данные конвейера по имени свойства или через входные данные параметра. В следующем сценарии, если мне нужно передать две строки по значению в Get-Command
для использования с параметром Module, я буду использовать командлет ForEach-Object
.
'ActiveDirectory', 'SQLServer' | ForEach-Object {Get-Command -Module $_} | Group-Object -Property ModuleName -NoElement | Sort-Object -Property Count -Descending
Count Name ----- ---- 147 ActiveDirectory 82 SqlServer
В предыдущем примере текущим объектом является $_
. Начиная с PowerShell версии 3.0 $PSItem
можно использовать вместо $_
. Но я встречаюсь с тем, что самые опытные пользователи PowerShell все еще предпочитают использовать $_
, так как он обеспечивает обратную и меньшую совместимость.
При использовании ключевого слова foreach
вы должны сохранить все элементы в памяти, прежде чем по ним проходить, а это может быть нелегкой задачей, если не знать, с каким количеством элементов вы работаете.
$ComputerName = 'DC01', 'WEB01' foreach ($Computer in $ComputerName) { Get-ADComputer -Identity $Computer }
DistinguishedName : CN=DC01,OU=Domain Controllers,DC=mikefrobbins,DC=com DNSHostName : dc01. mikefrobbins.com Enabled : True Name : DC01 ObjectClass : computer ObjectGUID : c38da20c-a484-469d-ba4c-bab3fb71ae8e SamAccountName : DC01$ SID : S-1-5-21-2989741381-570885089-3319121794-1001 UserPrincipalName : DistinguishedName : CN=WEB01,CN=Computers,DC=mikefrobbins,DC=com DNSHostName : web01.mikefrobbins.com Enabled : True Name : WEB01 ObjectClass : computer ObjectGUID : 33aa530e-1e31-40d8-8c78-76a18b673c33 SamAccountName : WEB01$ SID : S-1-5-21-2989741381-570885089-3319121794-1107 UserPrincipalName :
Цикл foreach
или ForEach-Object
нужно обязательно выполнить несколько раз, иначе вы получите сообщение об ошибке.
Get-ADComputer -Identity 'DC01', 'WEB01'
Get-ADComputer : Cannot convert 'System.Object[]' to the type 'Microsoft.ActiveDirectory.Management.ADComputer' required by parameter 'Identity'. Specified method is not supported. At line:1 char:26 + Get-ADComputer -Identity 'DC01', 'WEB01' + ~~~~~~~~~~~~~~~ + CategoryInfo : InvalidArgument: (:) [Get-ADComputer], ParameterBindingExc eption + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.ActiveDirectory.Management .Commands.GetADComputer
В других случаях вы можете получить те же результаты, одновременно удаляя цикл. Чтобы разобраться с параметрами, сверьтесь со справкой по командлетам.
'DC01', 'WEB01' | Get-ADComputer
DistinguishedName : CN=DC01,OU=Domain Controllers,DC=mikefrobbins,DC=com DNSHostName : dc01.mikefrobbins.com Enabled : True Name : DC01 ObjectClass : computer ObjectGUID : c38da20c-a484-469d-ba4c-bab3fb71ae8e SamAccountName : DC01$ SID : S-1-5-21-2989741381-570885089-3319121794-1001 UserPrincipalName : DistinguishedName : CN=WEB01,CN=Computers,DC=mikefrobbins,DC=com DNSHostName : web01.mikefrobbins.com Enabled : True Name : WEB01 ObjectClass : computer ObjectGUID : 33aa530e-1e31-40d8-8c78-76a18b673c33 SamAccountName : WEB01$ SID : S-1-5-21-2989741381-570885089-3319121794-1107 UserPrincipalName :
Как вы видите в предыдущих примерах, параметр Identity для Get-ADComputer
принимает только одно значение, если оно предоставлено с помощью входных параметров, и при этом позволяет получить несколько элементов, если входные данные предоставляются через входные данные конвейера.
Для
Цикл for
выполняет итерацию до тех пор, пока заданное условие имеет значение «Истина». Цикл for
я использую редко, но все же использую.
for ($i = 1; $i -lt 5; $i++) { Write-Output "Sleeping for $i seconds" Start-Sleep -Seconds $i }
Sleeping for 1 seconds Sleeping for 2 seconds Sleeping for 3 seconds Sleeping for 4 seconds
В предыдущем примере цикл будет повторяться четыре раза, начиная с числа 1, и продолжит выполняться до тех пор, пока переменная счетчика $i
не составит значение менее 5. Этот цикл будет бездействовать в течение всего 10 секунд.
Как нужно
В PowerShell существуют два разных цикла do
. Цикл Do Until
выполняется до тех пор, пока заданное условие имеет значение «Ложь».
$number = Get-Random -Minimum 1 -Maximum 10 do { $guess = Read-Host -Prompt "What's your guess?" if ($guess -lt $number) { Write-Output 'Too low!' } elseif ($guess -gt $number) { Write-Output 'Too high!' } } until ($guess -eq $number)
What's your guess?: 1 Too low! What's your guess?: 2 Too low! What's your guess?: 3
В предыдущем примере показана игра с цифрами, которая будет продолжаться до тех пор, пока значение, которое вы выдаете, не будет равняться тому же числу, которое было создано командлетом Get-Random
.
Цикл Do While
— полная противоположность. Он выполняется до тех пор, пока заданное условие не примет значение «Истина».
$number = Get-Random -Minimum 1 -Maximum 10 do { $guess = Read-Host -Prompt "What's your guess?" if ($guess -lt $number) { Write-Output 'Too low!' } elseif ($guess -gt $number) { Write-Output 'Too high!' } } while ($guess -ne $number)
What's your guess?: 1 Too low! What's your guess?: 2 Too low! What's your guess?: 3 Too low! What's your guess?: 4
Аналогичные результаты можно получить с помощью цикла Do While
, изменив условие проверки на значение «Не равно».
Циклы Do
всегда выполняются не менее одного раза, так как заданное условие вычисляется в конце цикла.
While
Цикл Do While
, как и цикл While
, выполняется до тех пор, пока заданное условие имеет значение «Истина». При этом различие состоит в том, что цикл While
принимает условие в верхней части цикла перед выполнением любого кода. Поэтому этот цикл не выполняется, если условие принимает значение «Ложь».
$date = Get-Date -Date 'November 22' while ($date.DayOfWeek -ne 'Thursday') { $date = $date.AddDays(1) } Write-Output $date
Thursday, November 23, 2017 12:00:00 AM
В предыдущем примере вычисляется, на какой день недели приходится День благодарения в США. Этот день всегда приходится на четвертый четверг ноября. Поэтому цикл начинается с 22-го дня ноября и добавляет один день, когда день недели не равен четвергу. Если на 22-е число выпадает четверг, цикл не выполняется.
Инструкции «Прервать», «Продолжить» и «Вернуть»
Инструкция Break
используется для прерывания цикла. Кроме того, она часто используется с инструкцией switch
.
for ($i = 1; $i -lt 5; $i++) { Write-Output "Sleeping for $i seconds" Start-Sleep -Seconds $i break }
Sleeping for 1 seconds
Инструкция break
, показанная в предыдущем примере, приводит к выходу цикла в первой итерации.
Инструкция «Продолжить» позволяет перейти к следующей итерации цикла.
while ($i -lt 5) { $i += 1 if ($i -eq 3) { continue } Write-Output $i }
1 2 4 5
В предыдущем примере выводятся числа 1, 2, 4 и 5. В нем исключается число 3 и выполняется переход к следующей итерации цикла. Инструкция break
, как и continue
, прерывает цикл, только если это не текущая итерация. Затем процесс переходит к следующей итерации, а не к прерыванию и остановке цикла.
Инструкция «Вернуть» позволяет выйти из существующей области.
$number = 1..10 foreach ($n in $number) { if ($n -ge 4) { Return $n } }
4
Обратите внимание, что в предыдущем примере функция return выводит первый результат, а затем выходит из цикла. Более подробное описание инструкции о результатах можно найти в одной из моих статей блога. The PowerShell return keyword
Сводка
В этой главе вы узнали о разных типах циклов, существующих в PowerShell.
Просмотр
- Чем отличается командлет
ForEach-Object
от конструкции сценариев foreach? - В чем основное преимущество использования цикла While от цикла Do while или Do Until?
- Как различаются инструкции «Прервать» и «Продолжить»?
Рекомендуем прочесть
- ForEach-Object
- about_ForEach
- about_For
- about_Do
- about_While
- about_Break
- about_Continue
- about_Return
Powershell Циклы — Stack Overflow на русском
Вопрос задан
Изменён
1 месяц назад
Просмотрен
5k раза
Подскажите, пожалуйста, как сделать цикл на powershell
для повторения строк N раз?
И что бы менялось имя при использовании get-newpass
каждый раз на другое, а не одно и тоже.
Пример:
function get-newpass { $string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" $chars =@() $chars += $string.GetEnumerator() $count = 12 return (Get-Random -InputObject $chars -Count $count) -join '' } $ksad = get-newpass $hiaosd = @" Hi me Friend $ksad "@ function cikl { #повтрить N раз $hiaosd }
- циклы
- powershell
- кодогенераторы
1
Если используя функции, то так:
$counter = 3 printer($counter) function printer ($counter){ for($i=1;$i -le $counter;$i++){ $print = get-newpass Write-Host("Hi me Friend "+$print) } } function get-newpass { $string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" $chars =@() $chars += $string.GetEnumerator() $count = 12 return (Get-Random -InputObject $chars -Count $count) -join '' }
Просто циклы:
for ($i = 1; $i -le 5; $i++) { $i } $i = 0; while ($i -lt 5) { $i++; $i } $i = 0; do { $i++; $i } until ($i -ge 5) foreach ($i in 1. $' (Get-Random -InputObject $chars -Count 12) -join '' } foreach ($i in 1..5) { test }
Зарегистрируйтесь или войдите
Регистрация через Google
Регистрация через Facebook
Регистрация через почту
Отправить без регистрации
Почта
Необходима, но никому не показывается
Отправить без регистрации
Почта
Необходима, но никому не показывается
By clicking “Отправить ответ”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.
PowerShell Foreach Loop — Javatpoint
следующий → Цикл Foreach также известен как оператор Foreach в PowerShell. Foreach — это ключевое слово, которое используется для цикла по массиву или набору объектов, строк, чисел и т. д. В основном этот цикл используется в тех ситуациях, когда нам нужно работать с одним объектом за раз. СинтаксисСледующий блок показывает синтаксис Цикл Foreach : Foreach ($ в $) В этом синтаксисе Блок-схема цикла ForEachПримерыПример 1: В следующем примере значение массива отображается с использованием цикла foreach : PS C:\> $Массив = 1,2,3,4,5,6,7,8,9,10 Вывод: 1 2 3 4 5 6 7 8 9 10 В этом примере массив $Array создается и инициализируется целочисленными значениями 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 . При первом выполнении оператора Foreach целочисленное значение ‘ 1 ‘ массива присваивается переменной $number . Затем он использует командлет echo для отображения числа 1. В следующий раз в цикле $number устанавливается равным 2 и так далее. После того как в цикле Foreach отображается число 10, PowerShell завершает цикл. Пример 2: В следующем примере показаны файлы папки с использованием цикла foreach : PS C:\> foreach($file в get-childitem) Вывод: Каталог: C:\ Режим LastWriteTime Длина Имя ---- ------------- ------ ---- д----- 23-02-2019 13:14 найдено.000 д----- 28-12-2017 19:44 Интел д----- 07-04-2018 10:53 Офис 2013 профессиональный плюс д----- 15-09-2018 13:03 PerfLogs д----- 09-10-2019 11:20 powershell д-р--- 22-08-2019 15:22 Программные файлы д-р--- 10.03.2019 10:23 Program Files (x86) В этом примере оператор foreach показывает список элементов (файлов), возвращаемых 9Командлет 0008 get-childitem . Example3: В следующем примере значение массива отображается с использованием цикла foreach: PS C:\> $fruits= «яблоко», «апельсин», «гуава», «гранат», «манго» Вывод: яблоко апельсин гуава гранат манго Next TopicWhile loop ← предыдущая |
Как использовать цикл Foreach в Powershell с примерами
Чем полезен цикл Foreach
Без цикла foreach выполнение одних и тех же действий более одного раза для нескольких элементов было бы утомительным и неэффективным. написание одних и тех же команд снова и снова отнимало бы много времени, но это было бы неэффективным использованием кода. Оператор foreach решает эту проблему.
Проще говоря, вы можете использовать оператор foreach, чтобы преобразовать такой фрагмент кода:
$report = [System.Collections. Generic.List[Object]]::new() $report += Get-Service -name BITS -RequiredServices | Выберите Имя, Тип услуги, Статус $report += Get-Service -name DHCP -RequiredServices | Выберите Имя, Тип услуги, Статус $report += Get-Service -name gpsvc -RequiredServices | Выберите Имя, Тип услуги, Статус $report += Get-Service -name iphlpsvc -RequiredServices | Выберите Name, ServiceType, Status
Во что-то более элегантное:
$services = Get-Service $report = [System.Collections.Generic.List[Object]]::new() Foreach ($Service в $Services) { $отчет += $сервис | Выберите Имя, Тип услуги, Статус }
Или даже:
Как вы можете видеть из вышеизложенного, код, который мог бы состоять из 50 строк, был сокращен до 5 строк или даже до 2 строк, если вы хотите быть действительно эффективным! Оба улучшенных примера отлично работают, однако, в зависимости от уровня опыта тех, кто читает ваш код, первый пример (с 5 строками) может быть легче читать и понимать.
$report = [System. Collections.Generic.List[Object]]::new() Получить-Сервис | Foreach-Object {$отчет += $_ | Select Name, ServiceType, Status}
Как написать цикл Foreach
Циклы Foreach имеют базовую структуру при их написании. За оператором foreach следуют квадратные скобки, а внутри скобок находится оператор в . Глядя на приведенную ниже структуру, $item определяет один элемент в каждом цикле цикла, а $itemcollection — это переменная, содержащая несколько элементов, которые проходят через цикл.
Затем следуют фигурные скобки (или фигурные скобки), а внутри этих скобок находятся команды, которые вы можете запускать для каждого элемента в коллекции, используя переменную $item .
Foreach ($item в коллекции $item) { "Сделай что-нибудь" $item }
Foreach и Foreach-Object
Хотя оператор foreach и командлет foreach-object выглядят одинаково, они служат разным целям. Смущает то, что foreach также является псевдонимом foreach-object, , поэтому, хотя назначение каждой команды одинаково, они используются немного по-разному.
По сути, при использовании оператора foreach ваша коллекция элементов сохраняется в памяти заранее в переменной, как в приведенном выше примере, где до использования оператора foreach мои элементы сохраняются в переменной $ коллекция предметов. Принимая во внимание, что командлет foreach-object предназначен для использования в вашем конвейере команд, и хотя его выполнение занимает больше времени, он имеет больше доступных параметров для использования.
Вы можете увидеть разницу в скорости между оператором foreach и командлетом foreach-object с помощью команды Measure-Command .
Начнем с измерения скорости работы Foreach-Object в нашем конвейере.
Команда измерения { $report = [System.Collections.Generic.List[Object]]::new() Получить-Сервис | Foreach-Object {$отчет += $_ | Выберите Имя, Тип услуги, Статус} }
Как видите, выполнение команды заняло в общей сложности 72 миллисекунды.
Measure Foreach-Object
Теперь посмотрим на скорость при выполнении той же команды с использованием оператора foreach .
Команда измерения { $services = Получить-Сервис $report = [System.Collections.Generic.List[Object]]::new() Foreach ($Service в $Services) { $отчет += $сервис | Выберите Имя, Тип услуги, Статус } }
Как видите, хотя в нашем сценарии разница во времени минимальна, команда была выполнена намного быстрее, за 47 миллисекунд по сравнению с использованием 9 миллисекунд.0008 для каждого объекта .
Measure Foreach
Цикл Foreach Примеры
Ниже приведены несколько различных примеров использования циклов foreach в PowerShell.
Запуск одной и той же команды для нескольких элементов
В простейшей форме, используя цикл foreach, вы можете запускать одну и ту же команду для нескольких элементов в коллекции. В приведенном ниже примере я вручную определил набор имен или служб, найденных на локальном компьютере. Затем я зациклился на каждом сервисе и запустил оба 9Команды 0008 stop-service и start-service , которые будут выполнять связанные действия с каждой службой.
$Services = "Spooler", "NetLogon", "dbupdate", "BITS" Foreach ($ сервис в $ сервисах) { Остановить сервис $service служба запуска }
Изменение настроек для нескольких элементов
Циклы Foreach можно использовать для более сложных задач, например, поскольку я часто работаю в Active Directory, мне может потребоваться изменить одно свойство для нескольких пользователей. В приведенном ниже примере я сохраняю всех пользователей с определенным параметром в переменной $users. Затем я перебираю каждого пользователя, чтобы изменить этот параметр на новое значение, в данном случае это параметр основного имени пользователя.
$users = Get-ADUser -Filter * | Где {$_.UserPrincipalName - соответствует "ourcloudnetwork.co.uk"} Foreach ($user в $users) { $upn = $user.UserPrincipalName.Replace("ourcloudnetwork.co.uk","ourcloudnetwork.com") Set-ADUser -Identity $user.SamAccountName -UserPrincipalName $upn }
Использование функций в цикле Foreach
При работе с более крупными сценариями, содержащими более сложные действия внутри цикла foreach , может иметь смысл переместить некоторые действия в функцию, а затем вызывать эту функцию изнутри петля. Хотя мой пример не совсем соответствует действительности, концепция остается той же для более сложных задач.
$olddomain = "ourcloudnetwork.com" $newdomain = "ourcloudnetwork.co.uk" функция Change-Upn { $upn = $user.UserPrincipalName.Replace("$olddomain","$newdomain") Set-ADUser -Identity $user. SamAccountName -UserPrincipalName $upn } $users = Get-ADUser -Filter * | Где {$_.UserPrincipalName -match "$olddomain"} Foreach ($user в $users) { Change-Upn }
Создание массивов с помощью цикла foreach
То, что я делаю почти каждый раз, когда использую цикл foreach строит некоторую форму массива. Массивы можно строить быстро и эффективно, используя foreach циклов. Сначала начните с создания пустого массива перед циклом foreach , а затем используйте оператор += , чтобы добавить новый элемент в ваш массив.
Ниже приведен простой пример, в котором мы перебираем каждый элемент, хранящийся в $items , затем перебираем каждый элемент и добавляем свойство элемента в массив.
$items = "1", "2", "3", "4", "5" $массив = @() Foreach ($item в $items) { $массив += $item.property }
Создание отчетов с помощью цикла foreach
Создание отчетов с помощью пользовательских объектов PowerShell — невероятно полезный навык. Хотя вы часто можете найти всю необходимую информацию с помощью соответствующих команд GET, построение отчета с циклом foreach позволит вам запросить дополнительную информацию о каждом элементе в коллекции и построить подробный отчет точно в соответствии с вашей необходимой информацией
В В приведенном ниже примере я опрашиваю всех пользователей в Active Directory, затем использую эту информацию для циклического просмотра каждого пользователя и запроса их почтового ящика Exchange с помощью команды Get-Mailbox.
$users = Get-ADUser -Фильтр * $Report = [System.Collections.Generic.List[Object]]::new() forEach ($user в $users) { $Псевдонимы = $нуль $почтовый ящик = $нуль $mailbox = Get-Mailbox -Identity $user.UserPrincipalName $Aliases = ($mailbox.EmailAddresses | ForEach-Object {$_ -replace "smtp:",""}) -join "," $obj = [PSCustomObject][заказанный]@{ "ОтображаемоеИмя" = $cuser.ОтображаемоеИмя "UserPrincipalName" = $cuser. UserPrincipalName "Псевдонимы" = $Псевдонимы } $отчет.Добавить($объект) }
Как видно из кода, я сначала создаю объект Collection с помощью:
$Report = [System.Collections.Generic.List[Object]]::new()
Затем я создаю собственный объект PowerShell, который добавляется в коллекцию с помощью следующего кода:
$report.Add($obj)
Создание вложенных циклов foreach
Вы также можете вложить операторов foreach в существующий оператор foreach . В приведенном ниже примере я создаю отчет о группах электронной почты в Exchange. Я перебираю каждую группу, затем получаю членов каждой группы и перебираю каждого члена, чтобы извлечь конкретную информацию и построить базовый отчет.
$Report = [System.Collections.Generic.List[Object]]::new() $GroupList = Get-DistributionGroup Foreach ($group в $grouplist) { $groupmembers = $нуль $groupmembers = Get-DistributionGroupMember -Identity $group. Name Foreach ($member в $groupmembers) { $obj = [PSCustomObject][Заказанный]@{ "Член" = $member.PrimarySmtpAddress "Тип участника" = $Member.RecipientType "Группа" = $Группа.Имя "Адрес группы" = $Group.PrimarySmtpAddress } $Отчет.Добавить($объект) } }
Интеграция операторов IF в цикл foreach
Подобно вложению операторов foreach , вы также можете вкладывать или интегрировать операторы IF в свои циклы для выполнения определенных действий на основе критериев или для обеспечения дополнительной проверки ошибок в ваших сценариях. . В очень элементарном виде мы можем реализовать оператор IF в нашем предыдущем примере, чтобы гарантировать, что мы зафиксируем в нашем отчете все группы, которые не содержат никаких элементов.
$Report = [System.Collections.Generic.List[Object]]::new()$GroupList = Get-DistributionGroup
Foreach ($group в $grouplist) {
$groupmembers = $нуль
$groupmembers = Get-DistributionGroupMember -Identity $group.