- PVSM.RU - https://www.pvsm.ru -
Кто, если не ты? Когда, если не сейчас?

В предыдущей части мы научились запускать PowerShell, разобрались с политикой выполнения сценариев. Поняли, что такое командлеты, знаем, как передавать их по конвейеру и как получить их свойства. Узнали, что PowerShell имеет огромный Help.
В этой части мы разберёмся с переменными, узнаем, что они за типы и как к ним обращаться, как их сравнивать и выводить всевозможными способами. Обязательно разберёмся с циклами и напишем несколько функций.
← Перейти к I части [1]
Начать я хочу с ответов на вопросы, возникшие в первом нашем с Вами Jump Start'е:
Изучить PowerShell точно стоит, если ты администрируешь Windows Server и серверное ПО от Microsoft. Возьмём, к примеру, один из популярнейших продуктов Microsoft Exchange Server — и тут же натыкаешься на PowerShell консоль Exchange Management Shell.
Зная PoSh ты без труда сможешь сделать любую нужную выгрузку данных, настроить контроль за любыми процессами системы, отправлять отчёты, создавать пользователей, решать их проблемы…
$var = 619
$var

$a = 1
$b = 2
$c = $a + $b
$c #c = 3
$str = "Хабра"
$str = $str + "хабр"
$str #str = Хабрахабр
$str = $str + 2014
$str #str = Хабрахабр2014
$s = "Это строка?"
$s.GetType().FullName

$var = "one"
[string]$var = "one"
PowerShell использует типы данных Microsoft .NET Framework. Рассмотрим основные:
| Тип / .NET класс | Описание |
|---|---|
| [string]
System.String |
Строка
|
| [char]
System.Char |
Символ
|
| [bool]
System.Boolean |
Булево. Может иметь значение $true или $false.
|
| [int]
System.Int32 |
32-разрядное целое число
|
| [long]
System.Int64 |
64-разрядное целое число
|
| [decimal]
System.Decimal |
128 битное десятичное число. Буква d на конце числа обязательна
|
| [double]
System.Double |
8-байтное десятичное число с плавающей точкой
|
| [single]
System.Single |
32 битное число с плавающей точкой
|
| [DateTime]
System.DateTime |
Переменная даты и времени.
|
| [array]
System.Object[] |
Массив. Индекс элементов массива начинается с 0 — чтобы обратиться к первому элементу массива $mas, следует написать $mas[0].
Для добавления элемента к массиву, можно записать
Каждый элемент массива может иметь свой тип
|
| [hashtable]
System.Collections.Hashtable |
Хеш-таблицы. Различие между хэш-таблицами и массивами в том, что в массивах используются индексы, а в хэш-таблице именованные ключи. Хеш-таблицы строятся по принципу: @{ ключ = «значение» }
Чтобы добавить элемент к хеш-таблице, можно или присвоить ей тот ключ, которого ещё нет, или воспользоваться методом Add(). Если присваивание делать к существующему ключу — значение ключа изменится на присваиваемое. Для удаления элемента из хеш-таблицы есть метод Remove().
|
Вы наверняка уже поняли, что в переменную можно записать не только какое-то определённое значение и заметили в таблице класс System.Object[]. В переменную так же можно записать вывод любого командлета.
Разберём боевую задачку: требуется узнать IP-адрес и MAC-адрес нескольких компьютеров в сети. Имена компьютеров domain-comp1, domain-comp2. Вариант решения под спойлером:
$MAC = Get-WmiObject -ComputerName domain-comp1, domain-comp2 -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=True | Select-Object -Property * | SELECT PSComputerName, @{Name="IPAddress";Expression={$_.IPAddress.get(0)}}, MACAddress, Description
$MAC
Мы записываем в переменную $MAC результат от выполнение командлета Get-WmiObject, с помощью которого передаём WMI запрос на компьютеры, указанные в параметре -computername и возвращаем нужную нам информацию из класса Win32_NetworkAdapterConfiguration.
Обратите внимание, если надо получить IP-адрес и MAC-адрес текущего компьютера, то вместо имён компьютеров, параметру -computername мы передадим точку. И, давайте, в следующим примере сохраним результат в файл D:comp_mac_ip.csv:
$MAC = Get-WmiObject -ComputerName . -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=True | Select-Object -Property * | SELECT PSComputerName, @{Name="IPAddress";Expression={$_.IPAddress.get(0)}}, MACAddress, Description
$MAC | Export-Csv D:comp_ip_mac.csv -Encoding UTF8
Область действия переменной в PowerShell может быть либо локальной, либо глобальной. По умолчанию переменная имеет локальную область действия и ограничена областью действия, например, доступна только в функции или только в текущем сценарии. Глобальная переменная действует во всём текущем сеансе PowerShell. Для того, чтобы обозначить глобальную переменную, достаточно написать следующую конструкцию: $Global: переменная = значение
$Global:var = 12
И ещё фишка по теме переменных… Как-то, обсуждая с коллегой 1С и его русскоязычную среду программирования, задались вопросом:
И да, действительно:
function привет() { "Привет, $env:USERNAME. Может не стоит писать на русском?"
Start-Sleep 3
"Открыть Хабр?"
}
function открывай() { & "C:Program FilesInternet Exploreriexplore.exe" http://habrahabr.ru/post/242425/ }

Операторы сравнения и логические операторы проверяют равенство или соответствие между двумя значениями.
В таблице ниже приведены операторы сравнения:
| Оператор | Описание | Пример |
|---|---|---|
| -eq | Equal / Равно (=) |
|
| -ne | Not equal / Не равно (<>) |
|
| -gt | Greater than / Больше (>) |
|
| -ge | Greater than or equal / Больше или равно (>=) |
|
| -lt | Less than / Меньше (<) |
|
| -le | Less than or equal / Меньше или равно (<=) |
|
| -like | Сравнение с учётом символа подстановки |
|
| -notlike | Сравнение с учётом не соответствия символа подстановки |
|
| -contains | Содержит ли значение слева значение справа |
|
| -notcontains | Если значение слева не содержит значение справа, получим истину |
|
| -match | Использование регулярных выражений для поиска соответствия образцу |
|
| -notmatch | Использование регулярных выражений для поиска несоответствия образцу |
|
| -replace | Заменяет часть или все значение слева от оператора |
|
Разберём пример. В примере мы формируем путь до возможного профиля пользователя на удалённом компьютере в зависимости от операционной системы. Решение под спойлером:
#Путь к профилю на удалённом компьютере
Function UProfile ($UCompName, $ULogin) {
[string]$CompOS = Get-WmiObject -ComputerName $UCompName -Class Win32_OperatingSystem | SELECT Caption #Получаем заголовок операционной системы компьютера
if ($CompOS -match "Windows 7") { #Если в заголовке содержится "Windows 7"
[string]$LinkUserProfile = "\$UCompNamed$users$ULogin" #Получаем такой путь
$LinkUserProfile
} elseif ($CompOS -match "Windows XP") { #Если в заголовке содержится "Windows XP"
[string]$LinkUserProfile = "\$UCompNamed$Documents and Settings$ULogin" #Получаем такой путь
$LinkUserProfile
}
}
UProfile domain-comp1 Administrator #функция имя-компьютера логин-пользователя
Да, здесь мы не проверяем, существует ли профиль. Но можно и проверить. Для этого добавим ещё одно условие, в котором будем проверять командлетом Test-Path существование пути:
#Путь к профилю на удалённом компьютере
Function UProfile ($UCompName, $ULogin) {
[string]$CompOS = Get-WmiObject -ComputerName $UCompName -Class Win32_OperatingSystem | SELECT Caption #Получаем заголовок операционной системы компьютера
if ($CompOS -match "Windows 7") { #Если в заголовке содержится "Windows 7"
[string]$LinkUserProfile = "\$UCompNamed$users$ULogin" #Получаем такой путь
} elseif ($CompOS -match "Windows XP") { #Если в заголовке содержится "Windows XP"
[string]$LinkUserProfile = "\$UCompNamed$Documents and Settings$ULogin" #Получаем такой путь
}
if (Test-Path $LinkUserProfile) { $LinkUserProfile } else { "Профиль $ULogin не существует на компьютере $UCompName" } #Проверяем существование профиля
}
UProfile domain-comp1 Administrator #функция имя-компьютера логин-пользователя
Кстати, регулярные выражение в PowerShell очень хорошо описал Xaegr [3] в своём блоге [4]. Стоит того, чтобы потратить пару часов на прочтение и постичь умение написания regular expressions.
$str1 = "Habr"
$str2 = "habr"
$str1 -ceq $str2 #$false
| Оператор | Описание | Пример |
|---|---|---|
| -and | Логическое и |
|
| -or | Логическое или |
|
| -not | Логическое не |
или
|
if ( условие1-верно ) { выполняем-код } #если условие 1 верно, выполняем код, если нет - идём дальше
elseif ( условие2-верно ) { выполняем-код } #необязательное условие: иначе, если условие 2 верно, выполняем код
else { выполняем-код } #необязательное условие: если прошлое условие не верно, выполняем код
Всё совсем просто. Если условие верно, мы выполняем следующий за условием код в фигурных скобках. Если условие не верно, то мы пропускаем выполнение и смотрим, продолжается ли у нас условие дальше.
Если находим elseif — проверяем новое условие и так же, в случае успеха, выполняем код, иначе, снова смотрим, есть ли продолжение в виде elseif или else.
Если условие выполняется, то код выполняется и ветка elseif или else пропускается.
$str = ""
if ( 1 -gt 2 ) { $str = "Апельсин" }
elseif ( $str -eq "Апельсин" ) { $str }
else { $str = "Яблоко"; $str }
Рассмотрим несколько основных вариантов вывода информации на экран:
$str = "Hello Habr!"
$str | Out-File D:out_test1.txt
или, как мы говорили в I части, использовать знак ">"
$str = "Hello Habr!"
$str > D:out_test2.txt
$p = Get-Process
$p | SELECT Name, Path | Export-Csv -Path D:out_test3.csv
$h = Get-Process
$h | ConvertTo-Html -Property Name, Path > D:out_test4.html
& D:out_test4.html #Откроем файле после формирования

Работать с HTML выводом на самом деле очень приятно. Имея навыки web-программирования можно добавить стилей и на выходе получить очень симпатичные отчёты.
Прочитать файл нам поможет уже знакомый нам командлет Get-Content
Get-Content D:out_test1.txt

Циклы в PowerShell мало чем отличаются от циклов в других языках. Почти всё как и везде:
Делать до тех пор, пока условие верно
$x = 10
do
{
$x
$x = $x - 1
}
while ($x -gt 0)
Цикл, который повторяет набор команд, пока выполняется условие
$x = 0
do
{
$x
$x = $x + 1
}
until ($x -gt 10)
Цикл, который повторяет одинаковые шаги определённое количество раз
for ($i = 0; $i -lt 10; $i++)
{
$i
}
Цикл по коллекции объектов
$collection = "Имя-Компьютера1", "Имя-Компьютера2", "Имя-Компьютера3"
foreach ($item in $collection)
{
$item
}
function имя-функции ([параметр1, ..., параметрN])
{
тело-функции
}
Например, функция для получения квадрата числа, на PowerShell будет выглядеть так:
function sqr ($a)
{
return $a * $a
}
sqr 2 #Результат: 4
И на последок, пример функции, которая поможет нам выполнять транслитерацию. В этом примере как раз всё то, что мы сегодня рассматривали:
#Транслитерация
function Translit ([string]$inString)
{
$Translit = @{ #Создаём хеш-таблицу соответствия символов
[char]'а' = "a"
[char]'А' = "A"
[char]'б' = "b"
[char]'Б' = "B"
[char]'в' = "v"
[char]'В' = "V"
[char]'г' = "g"
[char]'Г' = "G"
[char]'д' = "d"
[char]'Д' = "D"
[char]'е' = "e"
[char]'Е' = "E"
[char]'ё' = "yo"
[char]'Ё' = "Yo"
[char]'ж' = "zh"
[char]'Ж' = "Zh"
[char]'з' = "z"
[char]'З' = "Z"
[char]'и' = "i"
[char]'И' = "I"
[char]'й' = "j"
[char]'Й' = "J"
[char]'к' = "k"
[char]'К' = "K"
[char]'л' = "l"
[char]'Л' = "L"
[char]'м' = "m"
[char]'М' = "M"
[char]'н' = "n"
[char]'Н' = "N"
[char]'о' = "o"
[char]'О' = "O"
[char]'п' = "p"
[char]'П' = "P"
[char]'р' = "r"
[char]'Р' = "R"
[char]'с' = "s"
[char]'С' = "S"
[char]'т' = "t"
[char]'Т' = "T"
[char]'у' = "u"
[char]'У' = "U"
[char]'ф' = "f"
[char]'Ф' = "F"
[char]'х' = "h"
[char]'Х' = "H"
[char]'ц' = "c"
[char]'Ц' = "C"
[char]'ч' = "ch"
[char]'Ч' = "Ch"
[char]'ш' = "sh"
[char]'Ш' = "Sh"
[char]'щ' = "sch"
[char]'Щ' = "Sch"
[char]'ъ' = ""
[char]'Ъ' = ""
[char]'ы' = "y"
[char]'Ы' = "Y"
[char]'ь' = ""
[char]'Ь' = ""
[char]'э' = "e"
[char]'Э' = "E"
[char]'ю' = "yu"
[char]'Ю' = "Yu"
[char]'я' = "ya"
[char]'Я' = "Ya"
}
$TranslitText = ""
foreach ($CHR in $inCHR = $inString.ToCharArray())
{
if ($Translit[$CHR] -cne $Null)
{ $TranslitText += $Translit[$CHR] } #аналог записи $TranslitText = $TranslitText + $Translit[$CHR]
else
{ $TranslitText += $CHR }
}
return $TranslitText
}
Translit Хабрахабр #Вывод: Habrahabr
Теперь мы знаем достаточно информации, чтобы начать погружаться в PowerShell ещё глубже. В этой части мы встретились с переменными, типами данных, разобрались с выводом информации, операторами сравнения, циклами… Посмотрите, ведь начать, оказывается, не так уж и сложно!
Сохраняй спокойствие и учи PowerShell.
Автор: bgelov
Источник [10]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/73937
Ссылки в тексте:
[1] ← Перейти к I части: http://habrahabr.ru/post/242425/
[2] сюда: http://habrahabr.ru/post/60965/
[3] Xaegr: http://habrahabr.ru/users/xaegr/
[4] блоге: https://xaegr.wordpress.com/tag/regular-expressions/
[5] Скачать PowerShell v.4 бесплатно без регистрации: http://www.microsoft.com/ru-ru/download/details.aspx?id=40855
[6] Расширенные возможности и написание скриптов в PowerShell 3.0 (Jump Start): http://www.microsoftvirtualacademy.com/training-courses/advanced-tools-and-scripting-with-powershell-3-jump-start-russian
[7] Видео в тему на TechDays;: http://www.techdays.ru/videos/PowerShell
[8] Галерея скриптов PowerShell на Technet: https://gallery.technet.microsoft.com/scriptcenter/site/search?f%5B0%5D.Type=ProgrammingLanguage&f%5B0%5D.Value=PowerShell&f%5B0%5D.Text=PowerShell
[9] Блог разработчиков PowerShell: http://blogs.msdn.com/b/powershell/
[10] Источник: http://habrahabr.ru/post/242445/
Нажмите здесь для печати.