Foreach — Из Книги Powershell Подробно

Глава 19.3. В нем описывается конструкция Foreach и способы ее использования.

Эта конструкция преследует те же цели, что и командлет ForEach-Object. Командлет ForEach-Object имеет псевдоним ForEach, который легко спутать с оператором ForEach. поскольку они имеют одно и то же имя.

PowerShell просматривает контекст, чтобы определить, какой Foreach используется в данный момент. Вот пример того, как оператор и командлет делают одно и то же.

  
  
  
  
  
   

Get-Service –name B* | ForEach { $_.Pause() } $services = Get-Service –name B* ForEach ($service in $services) { $service.Pause() }

Давайте посмотрим, как работает оператор Foreach; в круглых скобках заключены две переменные, разделенные ключевым словом in. Вторая переменная, как и ожидалось, содержит один или несколько объектов, с которыми мы хотим что-то сделать.

Первая переменная предназначена для внутреннего использования; он будет содержать объект из второй переменной по очереди на каждом проходе.

Если вы писали на VBScript, подобные вещи должны показаться вам знакомыми.

Обычно вторую переменную называют во множественном числе, а первую – в единственном числе.

Это не требуется ни по соглашению, ни по стандарту, хотя вы можете написать Foreach( $Fred in $Rocvill), если $Rockvill содержит объекты, PowerShell с радостью справится с этим.

Но будьте внимательны при присвоении имен переменным, и вам придется запоминать гораздо меньше.

PowerShell автоматически берет один объект из второй переменной и помещает его в первую на каждом проходе цикла.

Внутри конструкции вы можете использовать первую переменную, чтобы что-то сделать с объектом, например, вы можете вызвать метод Pause этого объекта.

Не используйте $_ (или PSItem) в инструкции, как в командлете.

Иногда вы не можете быть уверены, какую конструкцию использовать — оператор или командлет. Теоретически конвейерная обработка объекта Foreach в некоторых ситуациях может использовать меньше памяти.

По нашим наблюдениям, с большими наборами объектов командлет работает медленнее.

Если у вас сложная обработка в конвейере, особенно если обработка осуществляется с помощью оператора Foreach внутри командлета Foreach, лучше использовать полное имя, чтобы четко определить, что именно используется.

Вам также необходимо быть осторожным, если вы хотите передать данные другому командлету или функции.

Пример

PS C:\> foreach ($service in $services) { >> $service | select Name,DisplayName,Status >> } | Sort Status >> An empty pipe element is not allowed. At line:3 char:4 + } | <<<< Sort Status + CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException + FullyQualifiedErrorId : EmptyPipeElement

PowerShell выдал ошибку, поскольку нечего было передать в конвейер для сортировки, но этот пример будет работать:

PS C:\> $services | foreach { >> $_ | select Name,DisplayName,Status >> } | Sort Status >> Name DisplayName Status ---- ----------- ------ Browser Computer Browser Stopped BDESVC BitLocker Drive Encrypt. Stopped bthserv Bluetooth Support Service Running BFE Base Filtering Engine Running BITS Background Intelligent .

Running

Другим фактором является то, понадобится ли вам снова использовать коллекцию объектов; если вам нужен сбор дальше, лучше использовать оператор, чтобы не получать данные повторно.

Последний момент заключается в том, что многие скрипты, которые вы найдете в Интернете, на самом деле являются конвертациями скриптов VBScript, в которых вам постоянно приходилось перебирать коллекции объектов.

Поэтому всегда стоит остановиться и на секунду подумать, чтобы определить лучший подход и нужно ли вообще перебирать коллекцию.

Наш совет – не применять грубую силу, если есть возможность этого не делать.

Например, давайте перепишем приведенный ранее код по-другому:

Get-Service –name B* | Suspend-Service

и пример сортировки будет выглядеть намного лучше, если написать так:

Get-Service b* | Sort Status | select Name,DisplayName,Status

Если по какой-то причине вам не нужно перебирать все объекты, не делайте этого.

Использование командлета или инструкции Foreach иногда является признаком того, что вы делаете что-то, чего делать не следует. Конечно, это не во всех случаях верно, но подумайте, сможет ли PowerShell выполнить часть работы за вас.

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

Важнее закончить работу, чем отслеживать, правильно или неправильно вы что-то написали.

вставка переводчика Имеется в виду возможность разработчика связывать параметры объектов на конвейере друг с другом по именам параметров.

Если есть вероятность, что поисковая система не сможет однозначно идентифицировать параметр объекта в процессе «привязки параметра», то ей придется перебирать объекты один за другим.

Например WMI. Общая рекомендация — использовать конвейерную обработку; цикл обычно прерывает конвейер и иногда приводит к ненужным итерациям.

Например, эффективнее выполнить Select и затем обработать, чем если бы внутри Foreach и обработать

Сейчас самое время напомнить вам о скобках.

Мы солгали, когда сказали, что для оператора Foreach требуются две переменные.

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

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

foreach ($service in (Get-Service –name B*)) { $service.pause() }

Эту версию сложнее читать, но она полностью легальна и избавляет от необходимости хранить промежуточные результаты в переменной.

Внутренние круглые скобки оцениваются первыми и создают коллекцию объектов, которые передаются дальше.

Теги: #PowerShell

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.