Цикл 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.

Просмотр

  1. Чем отличается командлет ForEach-Object от конструкции сценариев foreach?
  2. В чем основное преимущество использования цикла While от цикла Do while или Do Until?
  3. Как различаются инструкции «Прервать» и «Продолжить»?

Рекомендуем прочесть

  • 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 ($ в $)
{
Заявление-1
Заявление-2
Заявление-N
}

В этом синтаксисе — это отдельное значение переменной или объекта, которое изменяется на каждой итерации. <коллекция> — это массив или набор чисел и строк, к которым вы хотите получить доступ. Когда этот цикл выполняется, PowerShell создает переменную $ автоматически. В синтаксисе есть блок, который содержит один или несколько операторов, которые выполняются для каждого элемента в коллекции.

Блок-схема цикла ForEach

Примеры

Пример 1: В следующем примере значение массива отображается с использованием цикла foreach :

PS C:\> $Массив = 1,2,3,4,5,6,7,8,9,10
PS C:\> foreach ($число в массиве $)
>> {
>> эхо $число
>> }

Вывод:

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= «яблоко», «апельсин», «гуава», «гранат», «манго»
PS C:\> foreach ($item в $fruits)
>> {
>> эхо $item
>> }

Вывод:

яблоко
апельсин
гуава
гранат
манго
 

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.