Поиск по сайту:

HashTable PowerShell - Всё, что вам нужно знать


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

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

В этой статье мы рассмотрим хэш-таблицы и то, как использовать их в ваших скриптах PowerShell.

Хеш-таблица против массива

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

Массив - это индексированный список значений. Индекс автоматически генерируется, когда вы добавляете значения в массив. Поэтому вы не контролируете, где храните информацию в массиве.

$array = @('apple','raspberry','kiwi')

Мы можем получить доступ к элементам массива, перебирая их или обращаясь к элементам по их индексу:

$array | Foreach { Write-Host $_ }

Result
apple
raspberry
kiwi

Or by index number
write-host $array[1]

Result
raspberry

Мы также можем добавлять или обновлять значения в массиве, но мы не можем изменять или определять номер индекса элемента:

Replace the raspberry with melon
$array[1] = 'melon'

Add a fruit to the array
$array += 'banana'

Хэш-таблица

Как мы видели, массив — это просто список (коллекция) элементов, которые мы можем добавлять, изменять или удалять из списка. Индекс автоматически генерируется, когда вы добавляете элементы в него. Напротив, в HashTable PowerShell мы должны определить индекс (ключи) значения, которое мы хотим добавить.

Чтобы создать хэш-таблицу, мы используем {} вместо ():

Creating a hashtable
$serverIps= @{}

Or creating a pre-populate hashtable
$serverIps= @{
  'la-srv-lab02' = '192.168.10.2'
  'la-srv-db01' = '192.168.10.100'
}

Чтобы добавить IP-адрес сервера в хеш-таблицу, нам нужно определить ключ. Мы не можем просто $hashtable.add('value'), потому что хеш-таблица не создаст индекс автоматически.

$key = 'la-srv-lab01'
$value = '192.168.10.1'
$serverIps.add($key,$value)

Or simply
$serverIps.add('la-srv-lab03','192.168.10.3')

Result:
$serverips

Name                           Value
----                           -----
la-srv-lab03                   192.168.10.3
la-srv-lab01                   192.168.10.1

Ключом в этом случае является имя сервера, а значением - IP-адрес сервера. Если нам нужен IP-адрес сервера lab03, мы можем просто сделать следующее:

Извлечение данных из хэш-таблицы

Чтобы извлечь данные из хэш-таблицы в PowerShell, мы можем просто указать ключ, который вернет значение этого ключа:

$serverIps['la-srv-lab03']

Result
192.168.10.3

Другой вариант - пройти по хеш-таблице, но это работает немного иначе, чем с массивом. Если мы просто подключим цикл foreach к хеш-таблице, вы заметите, что он возвращает только объект хеш-таблицы:

$serverIps | foreach {write-host $_}
System.Collections.Hashtable

Чтобы получить только значения из хэш-таблицы, мы можем использовать свойство .value:

Return only the values
$serverIps.values

Or pipe them in a foreach to ping the servers for example:
$serverIps.values | foreach {ping $_}

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

$serverIps.GetEnumerator() | ForEach-Object {
   $result = '{0} IP address is {1}' -f $_.key, $_.value
   write-host $result
}

Result
la-srv-lab03 IP address is 192.168.10.3
la-srv-lab01 IP address is 192.168.10.1

Обновление значений

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

$serverIps['la-srv-lab03'] = '192.168.10.5'

Если вам нужно обновить несколько значений в хеш-таблице, вы не можете просто использовать цикл ForEach для перебора хеш-таблицы. Например, это не сработает:

$serverIps.Keys | ForEach-Object {
    $serverIps[$_] = '192.168.10.20'
}

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

$serverIps.Keys.Clone() | ForEach-Object {
   $serverIps[$_] = '192.168.10.20'
}

Удаление ключей или значений

Чтобы полностью удалить пару ключ/значение из хэш-таблицы, вы можете использовать функцию .remove. Вам нужно будет указать ключ, который вы хотите удалить:

$serverIps.Remove('la-srv-lab03')

Также возможно удалить только значение из ключа:

$serverIps['la-srv-lab03'] = $null

Чтобы полностью очистить хэш-таблицу, у вас есть два варианта: вы можете воссоздать экземпляр хэш-таблицы или использовать функцию clear. Последний вариант предпочтителен, так как он делает ваш код более читаемым.

Recreate the hashtable instance
$serverIps = @{}

Better option for readability, use the clear function
$serverIps.clear()

Разбиение хеш-таблиц

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

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

Send-MailMessage -SmtpServer smtp.contoso.com -To johndoe@a-d.site -From info@contoso.com -Subject 'super long subject goes here' -Body 'Test email from PowerShell' -Priority High

Чтобы сделать это более читаемым, мы можем использовать хэш-таблицу и распаковать ее. Распаковка заменяет все параметры и значения одной переменной. Обратите внимание, что мы используем символ @ для распаковки переменной вместо $.

$mail = @{
  SmtpServer  = 'smtp.contoso.com'
  To          = 'johndoe@a-d.site'
  From        = 'info@contoso.com'
  Subject     = 'super long subject goes here'
  Body        = 'Test email from PowerShell'
  Priority    = High
}

Note the @ infront of mail, instead of $
Send-MailMessage @mail

Как вы можете видеть, распаковка делает ваш код более понятным и легким для сопровождения вместо длинной строки параметров.

Создание объектов из хэш-таблиц

Хеш-таблицы отличны, когда вам нужно структурировать данные для одного объекта или для распаковки, но они не являются настоящими объектами. Хеш-таблицы имеют только два столбца: ключ и значение. Мы можем создать хеш-таблицу со спецификациями одного сервера, но когда нам нужно хранить данные о нескольких серверах, мы сталкиваемся с ограничениями (например, мы не можем повторно использовать имена столбцов).

Таким образом, лучший способ структурировать данные, когда у вас есть несколько записей, — это использовать объекты. Самый простой способ создать объекты в PowerShell — это преобразовать хеш-таблицу в пользовательский объект PowerShell. Мы делаем это, добавив [pscustomobject] перед хеш-таблицей.

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

$servers = @{
  'name'    = 'la-srv-db01'
  'ip'      = '192.168.10.100'
  'model'   = 'Hp DL380 G10'
  'memory'  = '96Gb'
}

Result
Name                           Value
----                           -----
memory                         96Gb
ip                             192.168.10.100
name                           la-srv-db01
model                          Hp DL380 G10

Как вы видите, у нас только два столбца: имя и значение. Хэш-таблица представляет собой один сервер, и мы не можем использовать её для создания списка серверов.

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

$servers = [pscustomobject]@{
  'name'    = 'la-srv-db01'
  'ip'      = '192.168.10.100'
  'model'   = 'Hp DL380 G10'
  'memory'  = '96Gb'
}

Result
name        ip             model        memory
----        --             -----        ------
la-srv-db01 192.168.10.100 Hp DL380 G10 96Gb  

Теперь мы можем добавить еще один сервер к pscustomobject:

function servers {
  [pscustomobject]@{
    'name'    = 'la-srv-db01'
    'ip'      = '192.168.10.100'
    'model'   = 'Hp DL380 G10'
    'memory'  = '96Gb'  
  }
  [pscustomobject]@{
    'name'    = 'la-srv-lab03'
    'ip'      = '192.168.10.3'
    'model'   = 'Hp DL180 G9'
    'memory'  = '32Gb'
  }
}

servers

Result
name         ip             model        memory
----         --             -----        ------
la-srv-db01  192.168.10.100 Hp DL380 G10 96Gb
la-srv-lab03 192.168.10.3   Hp DL180 G9  32Gb

Экспорт Hashtable в CSV

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

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

$serverIps= @{
  'la-srv-lab02' = '192.168.10.2'
  'la-srv-db01' = '192.168.10.100'
  'la-srv-lab03' = '192.168.10.3'
}

$serverIps.GetEnumerator() | Select Key, Value | Export-CSV -path c:\temp\hash.csv -No

Экспортировать хэш-таблицу в CSV

Заключение

Хеш-таблицы в PowerShell - это отличный способ структурировать данные или использовать их в сочетании с сплаттингом. Однако имейте в виду, что они предназначены для использования только для одного элемента. Мы не можем создать пользовательский столбец или сохранить несколько строк с одним и тем же ключом. Для этого вам действительно нужно использовать пользовательские объекты PowerShell.

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

Если вы хотите узнать больше о PowerShell, убедитесь, что вы также прочитали о 10 основных командах PowerShell, которые вы должны знать.