Функції та фільтри у PowerShell - PKI Extensions
У загальному значенні функції будуються за таким принципом:
Спочатку ми говоримо, що це буде функція і даємо їй ім'я. У дужках вказуємо список аргументів і після, у фігурних дужках вказуємо блок коду, який буде виконуватися при виклику функцій. Але функція сама собою малоцікава. Як правило, у неї передаються якісь дані і ми їх повинні якось отримувати всередині функції. Дані функції ми можемо передавати двома методами:
- використовуючи список аргументів (як у вказаному прикладі)
- по конвеєру
це дуже зручно, коли одним ключем за аналогією з командлет можна вибирати режим роботи функції. Просто у функціональності перевіряєте статус ключаTrue абоFalse і залежно від цього вибираєте режим.
Конвеєр та функції
Але часто нам зручніше передавати дані у функцію для обробки конвеєром. І ми, безумовно, можемо так робити. Але тут є свої тонкощі.
Ми захотіли просто помножити кожне число на 2. Але результату немає. Це друга часта помилка користувачів-початківців, які плутають функцію з конвеєрним цикломForeach-Object :
а ось тепер отримали очікуваний результат. Справа в тому, що в функцію дані надходять не в міру появи на вході конвеєра, а тільки коли конвеєр буде заповнений. Поки конвеєр наповнюється даними, вони містяться у спеціальну змінну$input у вигляді масиву. І лише після цього починає виконуватися саме тіло функції. Дивимося:
Однак, цей метод дуже непродуктивний, коли потрібно зробити деяку операцію над кожним елементом конвеєра. Оскільки ми повинні спочатку чекати, поки конвеєр буде зібрано всі дані в змінну$input і тільки потім почнеться сама обробка. Т.к.змінна$input є масивом, ми не можемо прямо до неї використовувати змінну поточного елемента$_. Як варіант, можна в самій функції розібрати змінну циклом$input і отримати необхідний результат:
Завдання хоч і вирішене, але, крім втрати продуктивності, у нас ще виріс обсяг коду. Що теж не є добре. Щоб позбутися від змінної $input можна використовувати етап функції - Process. Що це таке і з чим його їдять можна дізнатися із чудового поста Дмитра Сотнікова - $input Gotchas. Матеріал за посиланням викладено досить докладно і він буде зрозумілий навіть тим, хто має хоча б базові навички англійської мови. Отже:
на етапі Process ми відмовляємося у додатковому розборі змінної$input, оскільки етап Process починає виконуватися під час надходження першого елемента на вхід конвеєра. Отже, ми отримуємо виграш у швидкості роботи. Але для таких речей, як обробка кожного елемента в функції PowerShell є один різновид функції і називаєтьсяфільтр ! По суті, фільтр є тією ж функцією, яка поміщена в цикл Foreach-Object . Фільтри PowerShell використовуються так само, як і функції:
це те саме, що і:
Як бачите, варіантів розв'язання задачі у функціях існує багато і кожен може використовувати той, що йому до душі. Чи можна сказати, що це дрібниці? Так можна. Але саме такі дрібниці впливатимуть на естетичну красу, продуктивність і ресурсоспоживання ваших скриптів у роботі. Причомурізниця у продуктивності та ресурсоспоживання може сягати 100(!) раз, залежно від вибраного методу. Про це я вже говорив у своєму попередньому блозі на прикладі циклів: Foreach, Foreach-Object та оптимізація циклів у PowerShell.