Одна из новых возможностей Windows PowerShell версии 3 — новая форма синтаксиса командлетов Where-Object и ForEach-Object. Эти командлеты обычно принимают блок сценария (в случае Where-Object это называется сценарием фильтрации, потому что он должен возвращать $True или $False).
В блоке сценария символ $_ placeholder используется для обозначения «всего, что передано в командлет по конвейеру». Вот пример использования обоих командлетов (это не осмысленная, имеющая отношение к реальности команда, а просто демонстрация использования командлетов):
Get-WmiObject –class Win32_LogicalDisk |
Where-Object –filterscript{ $_.DriveType –eq 3 } |
ForEach-Object –process { $_.ChkDsk() }
Вы никогда не увидите эти команды именно в таком виде. Люди стараются использовать псевдонимы, урезанные имена параметров и позиционные параметры — все для того, чтобы поменьше вводить текста. Такая форма не редкость:
gwmi Win32_LogicalDisk |
? { $_.DriveType –eq 3 } |
% { $_.ChkDsk() }
Немного навороченного синтаксиса, чтобы быть незаменимым в компании, не повредит, не так ли? Новый синтаксис Where-Object позволяет вытворять такое:
gwmi Win32_LogicalDisk |
where DriveType –eq 3 |
% { $_.ChkDsk() }
Обратите внимание, что я переключился на другой псевдоним командлета. Как и раньше, можно использовать знак «?», но это меня буквально бесит. Я пришел из мира BASIC, где знак вопроса служил сокращением для команды Print. Чтение «?» в команде Windows PowerShell действует мне на нервы. Мне также не нравятся фигурные скобки и символ $_.
По существу, у Where-Object теперь есть позиционный параметр, принимающий свойство, на основе которого вы хотите выполнить фильтрацию (в моем примере это DriveType). В качестве параметров можно использовать все основные операторы Windows PowerShell (-eq, -ne, -like, -gt и т. д.). Значением параметра является значение, по которому вы хотите фильтровать (здесь это «3»). Такую сокращенную форму проще читать, но это можно использовать только для одного сравнения. Например, такой синтаксис не разрешается:
Gwmi Win32_Service |
Where StartMode –eq 'Auto' –and State –ne 'Running'
В таких ситуациях придется задействовать синтаксис старой школы:
Gwmi Win32_Service |
Where { $_.StartMode –eq 'Auto' –and $_.State –ne 'Running' }
В ForEach-Object также появилась похожая форма синтаксиса с сокращенной пунктуацией:
gwmi Win32_LogicalDisk |
where DriveType –eq 3 |
foreachChkDsk()
И на этот раз для удобства чтения я использовал псевдоним ForEach вместо %. Если вам больше нравится, можете использовать %. Один из моих коллег, носящих звание MVP, написал в блог замечательную заметку об этих сокращенных формах, которую стоит почитать: http://rkeithhill.wordpress.com/2011/10/19/windows-powershell-version-3-simplified-syntax. Он также предствавил обозначение $PSItem, которое похоже на альтернативу очень часто неправильно понимаемому символу $_.
Лично у меня новый синтаксис вызывает смешанные чувства. С одной стороны, он определенно облегчает новичкам освоение Powershell. Избавление от фигурных скобок и всегда приводящего в замешательство символа $_ — это замечательно. С другой стороны, эти формы не полностью функциональны. Они позволяют выполнять только одно сравнение. Вам все равно придется осваивать старый синтаксис.
Кроме того, никак не уйти от того факта, что старый синтаксис шесть лет использовался в блогах, журнальных статьях и книгах. Чтобы разобраться во всех этих примерах, все равно придется изучить старый синтаксис.
Поэтому новый синтаксис не избавляет от необходимости освоить старый синтаксис. Это означает, что теперь вам надо помнить две формы вместо одной. В любом случае с этим нам придется теперь жить.