Перечисления и последовательная обработка списков объектов – это очень важный для понимания вопрос. Потому как скрипты в основном пишутся для того, чтобы автоматизировать большое число однотипных ручных операций. И реализовать эту автоматизацию как раз позволяет последовательная обработка объектов или цикл, такой как ForEach-Object.
Разновидностей циклов существует несколько, но сегодня мы остановимся именно на ForEach-Object. Некоторые циклы могут выполняться бесконечно, но в данном случае мы имеем дело с перечислением. Это значит, что указанный набор действий будет выполнен над каждым объектом списка\коллекции один раз. Основные отличия от цикла For у ForEach-Object – более простая форма записи и меньшая гибкость в применении. В цикле For вы можете указать индекс начального объекта, шаг изменения индекса. Но, если стоит задача обработать один раз все объекты списка, то вам нужен ForEach-Object.
Способы использования и синтаксис
Существует несколько способов реализации перечислений:
- Применение в виде стандартного цикла;
- Применение в пайплайне (конвейере).
В связи с чем можно привести две общих формы записи. В первом случае сперва необходимо определить или получить набор объектов и сохранить его в переменную. И затем, используя командлет ForEach, выполнить обработку полученного набора объектов:
$spisok = object1, object2, object3 ... ForEach ($obj in $spisok) { any executable code with $obj } # где $obj - название переменной, в которой в тело скрипта передается очередной объект из списка
В случае с применением в пайплайне нет необходимости набор объектов сохранять в переменную. Вы просто передаете их по конвейеру на дальнейшую обработку.
object1, object2, object3 ... | ForEach-Object { any executable code with $PSItem }
Если в первом случае имя переменной, в которой содержится текущий обрабатываемый объект, мы определяли сами. То в данном случае используется зарезервированная переменная – $PSItem или его более короткий алиас $_. Так же в первом случае необходимо использовать только команду ForEach. Тогда как во втором случае ForEach-Object или более короткие алиасы для удобства – ForEach или %. Записи вида:
object1, object2, object3 ... | ForEach-Object { any executable code with $PSItem } # общепринятая форма записи. object1, object2, object3 ... | ForEach { any executable code with $PSItem } object1, object2, object3 ... | % { any executable code with $_ } # более удобная и компактная, но менее понятная форма записи.
будут работать абсолютно одинаково. Полную справку по камандлету можно посмотреть здесь ^
Примеры использования ForEach-Object.
Итак, чтобы увидеть как это работает, придумаем простую задачу по типу Hello World. В качестве подопытных возьмём моих коллег и поочередно выведем их имена в консоль.
$list = "Ivan", "Igor", "Andrey", "Artur", "Oleg", "Nikita", "Roman", "Valeriy", "Vladislav" ForEach ($item in $list) {Write-Host "$item the best!"}
В результате получим следующий вывод в консоли:
Ivan the best!
Igor the best!
Andrey the best!
Artur the best!
Oleg the best!
Nikita the best!
Roman the best!
Valeriy the best!
Vladislav the best!
Что было сделано – над каждым объектом из списка был выполнен код, указанный в блоке { }. С помощью командлета Write-Host мы вывели имена в консоль с добавлением текста. Я намеренно делаю акцент на том, что это не просто строки, а именно объекты. Любые объекты – это набор данных определенного типа, который имеет свойства (properties) и методы. И вы можете оперировать как объектами целиком, так и их отдельными свойствами.
Get-VM -Name v00* | Foreach {Set-VM -Name $_.name -StaticMemory -MemoryStartupBytes 8192MB}
В этом примере мы виртуальным машинам, у которых имя начинается на “v00”, установили статический объем ОЗУ – 8192MB. Обратите внимание, что в параметр -Name команды Set-VM передается не весь объект VM. А только ее имя – $_.name или $PSItem.name.
Анонс следующей статьи: “Переменные и массивы”.