Powershell Switch - это одна из особенностей, которое отличает язык команд от других. Самое первое условие, с которым мы начинаем работу в любых языках это IF. Его конструкция следующая:
If (Get-Item $way)
{
Get-Content $way
}
Чаще нам нужно использовать сразу несколько условий прибегая к конструкциям elseif и else:
$day = (Get-Date).DayOfWeek
$day
if ($day -eq 'Sunday'){$result = 'Воскресенье'}
elseif ($day -eq 'Monday'){$result = 'Понедельник'}
elseif ($day -eq 'Tuesday'){$result = 'Вторник'}
elseif ($day -eq 'Wednesday'){$result = 'Среда'}
elseif ($day -eq 'Thursday'){$result = 'Четверг'}
elseif ($day -eq 'Friday'){$result = 'Пятница'}
elseif ($day -eq 'Saturday'){$result = 'Суббота'}
else {$result = 'Неизвестно'}
$result
Такой подход очень частый в использовании и один из способов решения это использование switch.
Оператор Switch
В отличие от IF оператор Switch позволяет указывать переменную со значением единожды. Так будет выглядеть прошлый пример в варианте со Switch:
$day = (Get-Date).DayOfWeek
switch ($day)
{
'Sunday' {$rus_date = 'Воскресенье'}
'Monday'{$rus_date = 'Понедельник'}
'Tuesday' {$rus_date = 'Вторник'}
'Wednesday' {$rus_date = 'Среда'}
'Thursday' {$rus_date = 'Четверг'}
'Friday' {$rus_date = 'Пятница'}
'Saturday' {$rus_date = 'Суббота'}
}
$rus_date
Мы передали переменную $day единожды и нам не нужно каждый раз выполнять сравнение. После успешного сравнения переменная $rus_date примет указанное значение.
В случаях со сравнением не обязательно указывать кавычки, но рекомендуется так как в случае использования символов типа проблема мы получим ошибки.
Присвоение переменной
Предыдущий вариант можно еще больше сократить присвоив Switch в переменную:
$day = (Get-Date).DayOfWeek
$var = switch ($day)
{
'Sunday' {'Воскресенье'}
'Monday'{'Понедельник'}
'Tuesday' {'Вторник'}
'Wednesday' {'Среда'}
'Thursday' {'Четверг'}
'Friday' {'Пятница'}
'Saturday' {'Суббота'}
}
$var
По сути мы помещаем в переменную $var первый результат вернувший из конвейера True. Кроме строковых значений мы можем хранить и численные.
Default
Значение Default - это как else, который будет присвоен если ни одно значение не совпадет:
$month = (Get-Date).Month
$month_rus = switch ($month)
{
1 {'Январь'}
2 {'Февраль'}
3 {'Март'}
default {'Месяц не перечислен'}
}
$month_rus
Использование массивов
Мы можем использовать Switch с массивами. Будет проверено каждое значение, которое в нем находится. Пример ниже сработает только на ОС с русской локализацией иначе примется значение default:
$modules = (Get-Module).Name
$modules.GetType()
$modules_installed = switch($modules) {
'Dism' {'Управление дисками'}
'Microsoft.PowerShell.Management' {'Модуль для обслуживания систем'}
'Microsoft.PowerShell.Security' {'Модуль безопасности'}
default {'Такой модуль не указан'}
}
$modules_installed
После выполнения команды $modules_installed так же будет массивом вне зависимости от того сколько значений у нас было. Если у нас много одинаковых значений, то все они будут проверены.
Использование встроенных параметров
Мы можем использовать дополнительные параметры при использовании switch.
-Wildcard
Параметр Wildcard позволяет использовать маски. Для примера мы хотим найти слово 'параллелепипед' в какой-то длинной строке (тексте) и мы можем использовать четыре способа:
- *параллелепипед* - говорит о том, что мы может быть текст слева и справа.
- параллелепипед* - значит, что текст начинается с этого слова, но после него идет какой-то текст.
- *параллелепипед - текст заканчивается на это слово, но слева от него может быть текст.
- *пара*елепипед* - в этом случае подразумеваеться что есть текст до "пара", затем какое-то количество символов до "елепипед" и после него текст.
Если знаки * не указаны, то будет искаться точные соответствия:
$string = 'Как использовать swich в Powershell и не допустить ошибку'
$search = switch -Wildcard ($string){
'*Powershell*' {'Тут идет речь про Powershell'}
'*Ошибку' {'Тут так же идет речь про ошибки, регистр не важен'}
'Как*' {'Это слово ищется только в начале строки'}
'*Испо*ь*' {'Пропуск букв'}
'использовать' {'Это не найдется, так как не указан знак *'}}
$string
Такой вариант сработает и с массивами:
$array = 'Текст один', 'два'
$search = switch -Wildcard ($array){
'*оди*' {'Это текст один'}
'два' {'Точное соответствие'}}
$search
-regex
Так же как макси мы можем использовать регулярные выражения, но знак * в регулярных выражениях и масках работает по-разному. На примере ниже ищется IP адрес в массиве:
$regular_mask_ip = "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
$vals = 'smt','192.168.3.1','255.255.255.0','another var'
$find_ip = switch -regex ($vals){
$regular_mask_ip {'Похоже на IP: ' + $PSItem}
default {'Это не IP: '+ $PSItem}
}
Вы можете заметить, что мы можем передавать значение в виде переменных. $PSItem - это текущее значение, которое выполняется при сравнении. Чаще эту переменную указывают как "$_" .
-File
Отдельно и вместе с параметром маски и регулярных значений мы можем указывать и путь к файлу:
$path = 'C:\Windows\System32\drivers\etc\hosts'
$sw = switch -Wildcard -File $path {
"*localhost*" {'localhost прописан'}
"*127.0.0.1*" {'127.0.0.1 тоже прописан '}
}
$sw
-casesensitive
Casesensitive добавляет учет регистра при анализе:
$word = 'Text'
$sw = switch -CaseSensitive ($word){
"text" {'Не будет учтен, так как пишется с маленькой буквы'}
"texT" {'Буквы отличаются'}
"Text" {'Полное совпадение'}
}
$sw
Дополнительные возможности
В этой главе рассмотрим дополнительные возможности применения в скриптах.
Выражения
Вместе значения, которое мы передаем в switch, можно использовать командлет. Для примера так я найду отключенных пользователей не объявляя отдельную переменную:
$users = switch ((Get-LocalUser | where -Property Enabled -eq $False).Name){
'Гость' {"Пользователь $PSItem выключен"}
'Guest' {"Пользователь $PSItem выключен"}
'Администратор' {"Пользователь $PSItem выключен"}
'Administrator' {"Пользователь $PSItem выключен"}
}
Обратите внимание, что переменные включаются в строки при двойных кавычках.
Как работать с операторами сравнения в Powershell
Поиск дополнительных вхождений
Если условия поиска совпадут, то это не значит что совпадения не будут искаться дальше. Это имеет весомое значение, когда мы используем регулярные выражения:
$val = '192.168.1.1'
switch -Wildcard ($val){
'*.*' {'Тут сработало'}
'*1*' {'И тут сработало'}
'*2*' {'И тут'}}
О том как избежать возможных проблем будет рассмотрено дальше.
Continue
Когда нам нужно найти все совпадающие значение, но единожды, нужно использовать Continue. Результат работы хорошо виден с массивами:
$val = '1','2','3'
switch($val){
'1' {'Это значение больше не будет проверяться'
continue}
'1' {'Этого текста не будет'
continue}
'2' {'Первый раз 2'}
'2' {'Второй раз 2'}
}
На примере 2 видно, что она проверяется каждый раз, так как в ней не указан Continue. Такой же подход будет работать и при регулярных выражениях.
В этом сценарии 6 будет проверена дважды, так как предыдущее выражение используется раньше и не использует Continue:
$val = '6','5'
switch($val){
'6' {'Первый'
}
'6' {'Второй'
continue}
}
Break
В отличие от Continue при использовании Break выполнения сравнение прервется на 1 не проверяя дальнейшие значения:
$val = '1','2','3'
switch($val){
'1' {'Это значение больше не будет проверяться'
break}
'1' {'Этого текста не будет'
}
'2' {'Первый раз 2'}
'2' {'Второй раз 2'}
}
Так же как и в Continue чем ниже оно находится, тем больше сравнений будет выполнено:
$for_break = 'Inet1','Inet2','Inet3','Inet4'
switch($for_break){
'Inet1' {'Продолжение 1'}
'Inet2' {'Продолжение 2'
continue}
'Inet3' {'Остановка выполнения'
break}
'Inet4' {'Не будет использоваться'}
}
Дополнительные условия
Вместо значений с которыми мы сравниваем можно использовать дополнительные условия:
$kopilka = 3000
switch($kopilka){
{$PSItem -eq 3000}
{'Кушай доширак'
continue}
{$PSItem -le 6000}
{'Можно купить сосиски'
continue}
{$PSItem -le 9000}
{'Возьму в кредит iPhone'
continue}
default {'Моя копилка давно сломана'}
}
Можно добавить более интересные условия, но такой подход затруднит чтение кода. Скрипт ниже проверяет могут ли указанные пользователи менять пароль:
$case = 'Гость','Guest','Администратор','Administrator'
switch($case){
{(Get-LocalUser -Name $PSItem).UserMayChangePassword -eq $False}
{"Пользователь $PSItem не может менять пароль"
continue}
{(Get-LocalUser -Name $PSItem).UserMayChangePassword -eq $True}
{"Пользователь $PSItem может менять пароль"
continue}
default {"Пользователя $PSItem нет в базе"}
}
Использование переменной $matches
Когда мы использовали регулярные выражения в массиве, мы выводили значение массива. Когда нам нужно вывести значение найденное через регулярное выражение нужно использовать $matches:
$case = 'Text 1234 text'
switch -regex ($case){
'(?<num>\d\d\d\d)' {"В тексте такие цифры $($matches.num)"}
}
Powershell настраиваем IP адрес
$null
С помощь switch удобно проверять на пустые значения:
$str = @($null,'',' ','Значения')
switch ($str){
$null {continue}
' ' {continue}
'' {continue}
'Значения' {'Работает'}
}
Можно обернуть в функцию и обращаться к ней для проверки:
function Check-Null($var){
$result = switch ($var){
$null {$false
continue}
' ' {$false
continue}
'' {$false
continue}
default { $true
continue}
}
$result
return $result
}
Check-Null
Check-Null 'sss'
Вложенная проверка
Мы можем делать вложенную проверку, которая выполнит другие условия если первое является истиной. На примере ниже условия выполнятся если каждое из условий True:
# Объявляем имя пользователя
$user_name = 'Administrator'
# Получаем данные с AD
$user_data = Get-ADUser -Identity $user_name -Properties * | select *
# Узнаем устарел ли пароль (True или False)
$user_pass_exp = $user.PasswordExpired
# Заблокирован ли пользователь (True или False)
$user_locked = $user.LockedOut
# Если пользователь найден, то switch работает
$result = switch($user_data){
# Если пользователь заблокирован, он разблокируется
$user_locked {Unlock-ADAccount -identity $user_name}
# Если пароль устаревший, то пароль будет запрошен для смены.
$user_pass_exp {$password = Read-Host "Enter new password" -AsSecureString
Set-ADAccountPassword -Identity $user_name -NewPassword $password}
}
О том как получать данные пользователей из AD в Powershell вы можете почитать в предыдущих статьях.
...
Подписывайтесь на наш Telegram канал
Теги: #powershell