Все, что вы когда-либо хотели знать об инструкции switch

Что такое Windows PowerShell и с чем его едят? Часть 2: введение в язык программирования +44

  • 04.03.20 10:45


ruvds

#490924

Хабрахабр

14700

Блог компании RUVDS.com, Системное администрирование, Разработка под Windows, PowerShell
Рекомендация: подборка платных и бесплатных курсов создания сайтов — https://katalog-kursov.ru/

Исторически утилиты командной строки в Unix-системах развиты лучше чем в Windows, однако с появлением нового решения ситуация изменилась.
Для PowerShell можно писать сценарии на интерпретируемом мультипарадигменном языке, в котором есть элементы классического процедурного, объектно-ориентированного и даже функционального программирования: условный переход, циклы, переменные, массивы, хэш-таблицы, классы, обработка ошибок, а также функции, командлеты и конвейеры. Предыдущая статья была посвящена основам работы в среде, а сейчас мы предлагаем вниманию читателей небольшой справочник для программистов.

Передача через конвейер или Pipeline

Вы наверняка работали через команды Powershell, которые позволяли использовать конвейер следующим образом:

Если мы захотим использовать подход описанный выше, создав новые команды в виде функций, то конвейер не будет работать:

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

Таких атрибутов всего два:

  • ValueFromPipelineByPropertyName — получение значения из конвейера по имени;
  • ValueFromPipeline — получение через конвейер только значения .

Кроме этого, внутри нашей функции, мы должны добавить специальный блок Process. Наш скрипт в итоге будет выглядеть так:

— атрибут расширения функции, который добавляет некоторые возможности в функции позволяя им работать как команду.

Если бы мы не указали блок Process функция бы вернула только последней результат из массива 1..5:

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

Как уже писалось ValueFromPipelineByPropertyName принимает только именованные параметры и в случае с именем «bad» мы получаем ошибку:

  • Не удается привязать объект ввода к любым параметрам команды, так как команда не принимает входные данные конвейера
  • The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.

Причем передавать именованные параметры через хэш таблицы мы не можем, только через pscustomobject.

Вы можете указывать сразу два атрибута таким образом:

Это позволит использовать и значение с именем, если оно указано либо без него. Это не спасет вас от ситуации, если вы передаете параметр с другим именем:

Передача через конвейер нескольких значений

Для примера рассмотрим ситуацию, где нам нужно передать через конвейер два значения. Если Get-SomeNum будет возвращать массив, то через конвейер у нас будет проходить каждое число по отдельности. Это еще один повод использовать именованные параметры:

Подробное описание

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

Ключевое слово Ссылка
about_Functions, about_Functions_Advanced
about_Break, about_Trap
about_Try_Catch_Finally
about_Classes
about_Continue, about_Trap
about_Data_Sections
Зарезервировано для использования в будущем.
about_Do, about_While
about_Functions_Advanced_Parameters
about_If
about_If
about_Functions, about_Functions_Advanced_Methods
about_Enum
about_Functions
about_Try_Catch_Finally
about_For
about_ForEach
Зарезервировано для использования в будущем.
about_Functions, about_Functions_Advanced
about_Hidden
about_If
about_ForEach
about_Functions
about_Functions, about_Functions_Advanced
about_Return
about_Classes
about_Switch
about_Throw, about_Functions_Advanced_Methods
about_Trap, about_Break, about_Try_Catch_Finally
about_Try_Catch_Finally
about_Do
about_Using, about_Classes
Зарезервировано для использования в будущем.
about_While, about_Do

Рабочие процессы PowerShell используют следующие ключевые слова:

Рабочие процессы PowerShell поддерживаются только в PowerShell 5.1. Дополнительные сведения о рабочих процессах см. в разделе «Выполнение команд PowerShell в рабочем процессе».

Подробное описание

Оператор можно использовать для выполнения блоков кода, если заданный условный тест имеет значение true. Можно также указать один или несколько дополнительных условных тестов для выполнения, если все предыдущие тесты имеют значение false. Наконец, можно указать дополнительный блок кода, который выполняется, если ни один из предыдущих предварительных условных тестов не принимает значение true.

Синтаксис

В следующем примере показан синтаксис инструкции :

При выполнении инструкции PowerShell оценивает условное выражение как true или false. Если имеет значение true, выполняется, и PowerShell завершает инструкцию . Если имеет значение false, PowerShell оценивает условие, указанное условным оператором .

Дополнительные сведения о логическом вычислении см. в разделе about_Booleans.

Если имеет значение true, выполняется, и PowerShell завершает инструкцию . Если оба значения и имеют значение false, > выполняется блок кода, и PowerShell выходит из оператора If.

Вы можете использовать несколько инструкций для цепочки последовательности условных тестов. Таким образом, каждый тест выполняется только в том случае, если все предыдущие тесты имеют значение false. Если необходимо создать инструкцию , содержащую много операторов, рассмотрите возможность использования инструкции Switch.

Примеры:

Простейшая инструкция содержит одну команду и не содержит инструкций Elseif или других операторов. В следующем примере показана простейшая форма оператора :

В этом примере, если переменная $a больше 2, условие принимает значение true и выполняется список инструкций. Однако если $a меньше или равно 2 или не является существующей переменной, инструкция не отображает сообщение.

При добавлении оператора Else отображается сообщение, если $a меньше или равно 2. Как показано в следующем примере:

Для дальнейшего уточнения этого примера можно использовать оператор Elseif для отображения сообщения, если значение $a равно 2. Как показано в следующем примере:

Использование синтаксиса тернарного оператора

В PowerShell 7.0 появился новый синтаксис с использованием тернарного оператора. Он соответствует синтаксису тернарного оператора C#:

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

  • Выражение выполняется, если выражение имеет значение true.
  • Выражение выполняется, если выражение имеет значение false.

Пример:

В этом примере значение параметра — «Path exists» (Путь существует), если возвращает значение . Если возвращает значение , значение параметра равно «Путь не найден».

В этом примере, если служба запущена, она останавливается, а если ее состояние не выполняется, она запускается.

Оператор замены

Замена регулярными выражениями

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

Синтаксис:

Оператор заменяет все или часть значения указанным значением с помощью регулярных выражений. Оператор можно использовать для многих административных задач, таких как переименование файлов. Например, следующая команда изменяет расширения имен файлов для всех файлов на :

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

Примеры:

Подстановки регулярных выражений

Также можно использовать регулярные выражения для динамической замены текста с помощью захватывающих групп и подстановок. Группы отслеживания можно ссылаться в строке , используя знак доллара () перед идентификатором группы.

В следующем примере оператор принимает имя пользователя в формате и преобразуется в формат:

Предупреждение

Символ имеет синтаксические роли как в PowerShell, так и в регулярных выражениях:

  • В PowerShell между двойными кавычками она назначает переменные и выступает в качестве оператора подэкспрессии.
  • В строках поиска регулярных выражений он обозначает конец строки.
  • В строках подстановки регулярных выражений она обозначает захваченные группы. Обязательно поместите регулярные выражения между одними кавычками или вставьте перед ними символ обратной черты ().

Пример:

в regex обозначает литерал . Это в строке подстановки для включения литерала в результирующую замену. Пример:

Дополнительные сведения см. в разделе about_Regular_Expressions и .

Замена блоком скрипта

В PowerShell 6 и более поздних версий оператор также принимает блок скрипта, выполняющий замену. Блок скрипта выполняется один раз для каждого совпадения.

Синтаксис:

В блоке скрипта используйте автоматическую переменную для доступа к замещаемого входного текста и другой полезной информации. Тип класса этой переменной — System.Text.RegularExpressions.Match.

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

Try как источник неустранимой ошибки

Кирк Манро указывает, что некоторые исключения являются неустранимыми ошибками только при выполнении внутри блока . В этом предоставленном им примере исключение во время выполнения вызывается вследствие деления на ноль.

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

Однако если поместить этот же код в , то происходит нечто иное.

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

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

Метод $PSCmdlet.ThrowTerminatingError() в try/catch

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

Шаблоны общих функций

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

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

Сохранение, загрузка и импорт

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

Импорт на множество компьютеров

Если это командлет, который будет использоваться на множестве компьютеров или вы его планируете использовать короткое время, то скрипт можно сохранить в файл с расширением «.ps1». Загрузка такой функции будет выполняться так:

После выполнения этой команды мы сможем использовать нашу функцию.

Минус такого способа в том, что нужно будет делать каждый раз после закрытия консоли (сессии).

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

Загрузка как модуля

Если вы планируете использовать функцию на своем компьютере, то вы можете загрузить эту команду как модуль. Вы можете использовать и на других компьютерах, но я считаю это плохим вариантом.

Первое что нужно сделать это получить пути окружения Powershell:

Выберете один из путей, где лежат модули или перейдите по следующему:

В указанной папке Modules вам нужно создать папку и файл с одинаковыми именами. Файлу добавляете расширение «.psm1» и помещаете в него свой скрипт.

В моём случае путь выглядит так:

После этого закройте все окна Powershell и откройте заново. Модуль будет импортироваться автоматически. Проверти что он загружен можно с помощью команды:

Рекомендую

Операторы равенства

-eq и -ne

Если левая сторона скалярна, возвращает значение True, если правая сторона является точным совпадением, в противном случае возвращает значение False. делает противоположное; возвращает значение False , если обе стороны совпадают; в противном случае возвращает значение True.

Пример

Если левая сторона является коллекцией, возвращает те элементы, которые соответствуют правой части, а фильтрует их.

Пример

Эти операторы обрабатывают все элементы коллекции. Пример

Оператор равенства может сравнивать объекты разных типов

Важно понимать, что значение находится в правой части сравнения, можно преобразовать в тип левого значения для сравнения

Например, строка преобразуется в целое число, которое будет сравниваться со значением . В этом примере возвращается .

В этом примере значение преобразуется в строку для сравнения со строкой . В этом примере возвращается .

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

В этом примере мы создали два объекта с одинаковыми свойствами. Тем не менее результат проверки на равенство имеет значение False , так как они являются разными объектами. Чтобы создать сопоставимые классы, необходимо реализовать System.IEquatable<T> в классе. В следующем примере демонстрируется частичная реализация класса MyFileInfoSet , реализующего System.IEquatable<T> , и имеет два свойства: File и Size. Метод возвращает значение True , если свойства File и Size двух объектов MyFileInfoSet одинаковы.

Выдающийся пример сравнения произвольных объектов — выяснить, являются ли они пустыми. Но если необходимо определить, является ли переменная, необходимо поместить в левую часть оператора равенства. Положив его на правую сторону, не делает то, что вы ожидаете.

Например, позвольте быть массивом, содержащим пустые элементы:

Следующие тесты, не имеющие значения NULL.

Однако следующие файлировщики из всех элементов NULL из:

-gt, -ge, -lt и -le

, , и вести себя очень аналогично. Если обе стороны являются скалярными, они возвращают значение True или False в зависимости от того, как две стороны сравнивают:

Оператор Возвращает значение True, если…
Левая сторона больше
Левая сторона больше или равна
Левая сторона меньше
Левая сторона меньше или равна

В следующих примерах все операторы возвращают значение True.

Примечание

В большинстве языков программирования оператор больше, чем оператор . В PowerShell этот символ используется для перенаправления. Дополнительные сведения см. в разделе about_Redirection.

Если левая сторона является коллекцией, эти операторы сравнивают каждый элемент коллекции с правой стороны. В зависимости от их логики они сохраняют или отклоняют член.

Пример

Эти операторы работают с любым классом, реализующим System.IComparable.

Примеры:

В следующем примере показано, что на американской клавиатуре QWERTY нет символа, который сортируется после «a». Он передает набор, содержащий все такие символы оператору , чтобы сравнить их с «a». Выходные данные являются пустым массивом.

Если две стороны операторов не являются достаточно сопоставимыми, эти операторы вызывают ошибку без конца.

powershell — Создание цикла for для консолидации сценария с помощью командной строки powershell

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

Большая часть кода используется повторно, и я хотел бы объединить его в один цикл for-loop, но мой PShell-foo еще не достиг уровня черного пояса. Я знаком с вводом CSV для переменных с переменной переменной, но думаю, что это можно сделать с помощью массива, сгенерированного в коде. Может ли один из вас обучить этот неофит?

Вот санированная версия текущего кода:

EDIT: взяв код TheMadTechnician, я упростил его и запустил, чтобы посмотреть, что происходит. Вот тестовый код:

Вот результат (в блоке кода, потому что я еще не могу опубликовать изображения):

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

Подробное описание

Оператор можно использовать для выполнения блоков кода, если заданный условный тест имеет значение true. Можно также указать один или несколько дополнительных условных тестов для выполнения, если все предыдущие тесты имеют значение false. Наконец, можно указать дополнительный блок кода, который выполняется, если другой условный тест не имеет значения true.

Синтаксис

В следующем примере показан синтаксис инструкции :

При выполнении инструкции PowerShell вычисляет условное выражение как true или false. Если значение равно true, выполняется и PowerShell завершает инструкцию . Если значение равно false, PowerShell вычисляет условие, указанное условным оператором.

Дополнительные сведения о логическом вычислении см. в about_Booleans.

Если значение равно true, выполняется и PowerShell завершает инструкцию . Если оба значения имеют значение false, > блок кода выполняется, и PowerShell завершает инструкцию If.

Для цепочки последовательности условных тестов можно использовать несколько инструкций. Таким образом, каждый тест выполняется только в том случае, если все предыдущие тесты имеют значение false. Если необходимо создать инструкцию , содержащую множество инструкций, рассмотрите возможность использования инструкции Switch.

Примеры:

Простейшая инструкция содержит одну команду и не содержит никаких операторов Elseif или любых операторов Elseif. В следующем примере показана простейшая форма оператора:

В этом примере, если переменная $a больше 2, условие возвращает значение true, а список инструкций выполняется. Однако если $a меньше или равно 2 или не является существующей переменной, инструкция не отображает сообщение.

Добавив оператор Else, сообщение отображается, если $a меньше или равно 2. Как показано в следующем примере:

Чтобы дополнительно уточнить этот пример, можно использовать оператор Elseif для отображения сообщения, если значение $a равно 2. Как показано в следующем примере:

Использование синтаксиса тернарного оператора

В PowerShell 7.0 появился новый синтаксис с помощью тернарного оператора. Он соответствует синтаксису тернарного оператора C#:

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

  • Выражение выполняется, если выражение имеет значение true.
  • Выражение выполняется, если выражение имеет значение false.

Пример:

В этом примере значение «Путь существует» при возврате . При возвращении значение равно «Path not found» (Путь не найден).

В этом примере, если служба запущена, она останавливается и, если ее состояние не выполняется, она запускается.

$null.Count

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

Если у вас есть значение , то равняется . Это специальное свойство добавляется PowerShell.

Count

Почти у всех объектов в PowerShell есть свойство Count. Одним из примечательных исключений является в Windows PowerShell 5.1 (что было исправлено в PowerShell 6.0). У него нет свойства Count, поэтому при попытке его использования вы получаете значение . Я вспомнил это к тому, чтобы вы не пытались использовать вместо проверки .

Выполнение этого примера в Windows PowerShell 5.1 и PowerShell 6.0 дает разные результаты.

Пустое значение NULL

Существует один особый тип , который отличается от остальных. Я буду называть его пустым значением , тогда как фактически это System.Management.Automation.Internal.AutomationNull. Такое пустое значение вы получаете в результате выполнения функции или блока скрипта, которые не возвращают ничего (возвращают void).

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

Можно создать массив с одним значением , при этом его свойство будет равно . Но если поместить пустой результат в массив, он не будет считаться элементом, а Count будет иметь значение .

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

Если передать пустое значение в параметр функции, который не является строго типизированным, PowerShell по умолчанию приводит значение Nothing к значению . Это означает, что внутри функции значение будет обрабатываться как вместо типа System.Management.Automation.Internal.AutomationNull.

Pipeline

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

В зависимости от кода следует учитывать в логике.

В любом случае сначала выполните проверку на соответствие :

  • В конвейере отфильтруйте значение NULL().
  • Задайте его обработку с помощью функции конвейера.

Использование break циклов

Когда оператор отображается в цикле, например , или цикле, PowerShell немедленно завершает цикл.

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

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

В этом примере оператор завершает цикл, когда переменная равна 1. Несмотря на то, что инструкция имеет значение True , пока не будет больше 10, PowerShell достигнет оператора break при первом запуске цикла.

Чаще всего оператор используется в цикле, где должно выполняться внутреннее условие. Рассмотрим следующий пример инструкции:

В этом примере инструкция выполняет итератор массива . Оператор вычисляет значение False в первый раз, когда цикл выполняется, а переменная увеличивается на 1. Третий раз, когда цикл выполняется, равен 2, а переменная равна 30. На этом этапе выполняется инструкция и цикл завершается.

Использование метки в цикле

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

перемещает выполнение из помеченного цикла. В внедренных циклах это результат отличается от ключевого слова, если он используется самостоятельно. В этом примере есть оператор с оператором :

Если условие 2 имеет значение True, выполнение скрипта пропускается до оператора после помеченного цикла. В примере выполнение начинается снова с оператора .

Можно вложить много помеченных циклов, как показано в следующем примере.

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

Если переменная имеет значение True, выполнение возобновляется после самого внутреннего цикла. Метка не требуется.

PowerShell не ограничивает, насколько метки могут возобновить выполнение. Метка может даже передавать управление между границами вызовов скриптов и функций.

Перенаправление вывода в $null

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

Назначение в $null

Результатам команды можно назначить значение , что будет аналогично использованию .

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

Перенаправление в $null

Можно также использовать оператор перенаправления для отправки выходных данных в .

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

Рейтинг
( Пока оценок нет )
Editor
Editor/ автор статьи

Давно интересуюсь темой. Мне нравится писать о том, в чём разбираюсь.

Понравилась статья? Поделиться с друзьями:
Работатека
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: