Особенности работы с массивами в PowerShell. Powershell работа с массивами
Особенности работы с массивами в PowerShell
Обычно массив представляет из себя набор компонентов (элементов массива), расположенных друг за другом в определенном порядке. Каждый элемент массива имеет свой порядковый номер, а доступ к элементам массива осуществляется при помощи индексации, т.е. по ссылке с указанием номера (индекса) нужного элемента. Но массив не обязательно должен состоять из нескольких элементов, он может включать в себя только один элемент или вообще быть пустым.
При работе с массивами необходимо помнить о том, что по умолчанию PowerShell пытается самостоятельно определить тип данных. Для примера возьмем переменную и поместим в нее несколько чисел, а затем проверим тип данных в переменной:
$a = 1, 2, 3 $a.GetType()
Как видите, в данном случае мы получаем массив (System.Array). Но если в переменную поместить одно значение, то PowerShell не будет формировать массив:
$b = 1 $a.GetType()
Как видно из примера, PowerShell определяет тип данных в переменной в зависимости от количества объектов. Но мы не всегда можем точно заранее сказать, сколько объектов будет получено в результате выполнения той или иной команды, поэтому необходимо иметь код, который будет всегда рассматривать результат как массив.
Сделать это можно разными способами, например с помощью оператора ″,″ . Если запятая используется как бинарный оператор, то создается обычный массив, а если как унарный — то массив с одним элементом. Например так получим массив, состоящий из одного элемента:
$b = ,1
Можно явно указать тип данных в переменной, не давая PowerShell простора для фантазии, например так:
[object[]]$b = 1
Здесь надо упомянуть, что каждый элемент массива также имеет свой тип данных, а тип object[] позволяет добавлять в массив любые объекты. При необходимости можно ограничить члены массива определенным типом данных (типизированный массив). Например можно указать в качестве элементов массива только целочисленные значения:
[int32[]]$b = 1
А так мы определим в качестве членов массива системные процессы:
[System.Diagnostics.Process[]]$b = Get-Process
Также создать массив можно с помощью оператора подвыражения массива ″@″, который формирует массив в любом случае, даже при полном отсутствии объектов. Очень удобно сначала инициализировать переменную как массив, а затем добавлять в нее нужные объекты, не беспокоясь об их количестве:
$b = @()$b = 1
Ну и в завершение еще один способ, подсмотренный на MSDN. Его суть в том, что объекты передаются по конвейеру специальной функции, которая преобразует их в массив. Выглядит примерно так:
function Out-Array {begin {$out = @()}; process {$out += $_}; end {return, $out}} $b = 1 | Out-Array
Способ не самый прямой и не самый быстрый, но вполне рабочий.
windowsnotes.ru
PowerShell для программиста. Массив массивов в PowerShell
Уже несколько раз столкнулся с особенностями создания различных иерархий посредством массивов и хешей. И если с ассоциативными массивами (хэшами) проблем как правило нет, то вот с обычными уже как карта ляжет. Проблема в том, что PowerShell пытается додумывать и незримо конвертировать типы. Решил увековечить в общем.
Как думаете, что будет результатом выражения:$a = @(1,2,3,@(4,5,6))
Правильно! Одномерный массив @(1,2,3,4,5,6)
А вот что бы не произошло объединения массивов, а все таки 4-й элемент стал именно вложенным массивом надо добавить магическую запятую:$a = @(1,2,3, , @(4,5,6))
Собсно, везде где мы хотим что бы массив остался массивом, самый простой вариант это добавить запятую впереди. Можно конечно работать с каким-нибудь C# массивом/коллекцией (соответствующим образом объявив) и там проблем не будет.
Ниже полный код скрипта где реализованы примеры вложенных массивов и хэшей на примере простейшей рекурсивной функции. Для наглядности результата сделал преобразование в JSON.Конструкции -replace “\s”,”” – реализуют минификацию, можно убрать – будет развернутый JSON
clear function RecursionHash($deep) { $la = @{} $la["item$deep"] = "Iteration $deep" if ($deep -gt 0) { $la["sub"] = RecursionHash -deep ($deep-1) } return $la } function RecursionArray($deep) { $la = @() if ($deep -gt 0) { $la += ,@((RecursionArray -deep ($deep-1)), "Iteration $deep") # comma is a magic } return $la } $hash = RecursionHash -deep 3 (ConvertTo-Json $hash) -replace "\s","" $arr = RecursionArray -deep 3 (ConvertTo-Json $arr) -replace "\s",""Собака нужна, как явное объявление и инициализация типа, иначе самый глубокий элемент будет не понять чем (в данном случае пустой хэш почему-то):$la += ,((RecursionArray -deep ($deep-1)),$deep)[[[[[{},1],2],3],4],5]
А перед ней запятая, что бы последний (глубокий) элемент именно вложился в предпоследний, а не добавился к предпоследнему массиву:$la += @((RecursionArray -deep ($deep-1)),$deep)[[[[1,2],3],4],5](собаку можно было и не ставить, тут даже PoSh-у понятно ч
vms11.wordpress.com
Массивы в Windows PowerShell, часть 2
Продолжаем разговор о массивах в Windows PowerShell. В предыдущей части мы говорили об обращении к элементам массива. Сегодня поговорим об операциях с массивом.
Операции с массивом
По умолчанию все массивы в PowerShell являются полиморфными, т.е. способны содержать в себе элементы разных типов.
Давайте создадим массив $a, состоящий, к примеру, из трех элементов 1, 2 и 3. И проверим его тип на практике.
Итак, как видим, для того, чтобы посмотреть тип массива $a, нам нужно набрать
$a.GetType().FullNameи мы увидим, что это массив типа System.Object[]. Такие массивы могут содержать объекты всех типов.
Мы можем создать массив с жестко заданными элементами одного типа. Для этого при создании массива перед его именем нужно прописать в квадратных скобках нужный нам тип переменных.
[int[]]$a=1,2,3Если мы попытаемся перезаписать значение элемента такого массива на что-нибудь неподходящее, мы увидим следующее сообщение об ошибке:
Теперь поговорим о том, как можно изменять уже существующие массивы.
К примеру, наш массив $a имеет три элемента, если мы попытаемся обратиться к элементу, выходящему за границы массива, PowerShell просто проигнорирует нас. А вот если мы попытаемся изменить значение несуществующего элемента, нас встретит сообщение об ошибке.
Если нам нужно увеличить длину массива, мы можем использовать операторы + или +=.
По факту, в данном случае мы не добавили элементы к существующему массиву, а создали новый, в который было скопировано содержимое старого массива и добавлены новые элементы.
По той же логике мы не можем удалить элементы из уже существующего массива, но мы можем создать новый массив и скопировать туда все элементы, кроме ненужных.
Объединить массивы довольно просто.
Для удаления массива нужно воспользоваться командлетом Remove-Item (псевдоним del) и удалить массив с виртуального диска variable. Ниже пример удаления массива $a.
И последнее, что нужно знать о массивах. Если мы просто используем оператор присваивания (=), то новый массив будет своеобразной ссылкой на предыдущий. К примеру, $b=$a создаёт массив $b, который ссылается на $a. Если мы изменим значения элементов массива $a, то они изменятся и в $b. Данное правило не касается массивов, полученных из объединения других.
webistore.ru
Массивы в Powershell: yu_xuan
При написании скриптов массивы используются очень часто, поэтому необходимо хорошо понимать как работать с ними.Создать массив в powershell можно просто перечислив его члены через запятую. Для примера создадим небольшой массив, состоящий из чисел:
PS C:\> 1,2,3,4 1 2 3 4PS C:\> (1,2,3,4).GetType().FullName System.Object[]Как видно из предыдущего примера, массив имеет тип Object, то есть это означает, что членам массива может быть присвоен любой объект:
PS C:\> 1, 2.5, "apples", (Get-Process winword) 1 2,5 apples Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName ------- ------ ----- ----- ----- ------ -- ----------- 1333 86 47844 66728 350 581,15 10448 WINWORDPS C:\> (1, 2.5, "apples", (Get-Process winword)).Count 4В предыдущем примере создан массив объектов, содержащий число, число двойной точности с плавающей запятой, строку и объект Process, т.е. всего четыре объекта: int, double, string, System.Diagnostics.Process instance.
Для создания массива используется довольно свободный синтаксис, однако существует формальный способ, заключающийся в использовании конструкции @() :
PS C:\> @("one", "two") one twoДля создания пустого массива можно воспользоваться следующим способом:
PS C:\> (@()).Count 0PS C:\> (@()).GetType().FullName System.Object[]Для удобства массив можно создавать, указывая необходимый диапазон чисел:
PS C:\> 5..1 5 4 3 2 1PS C:\> 1..5 1 2 3 4 5PS C:\> (0..255).Count 256Такой синтаксис чрезвычайно удобно использовать для перечисления большого набора упорядоченных чисел таких как номера портов или адреса.
При создании массивов powershell умеет распознавать вложенные массивы и превращать их в один массив:
PS C:\> 1, (5, 6), 2 1 5 6 2PS C:\> 1, (10..7), 2 1 10 9 8 7 2Получить доступ к члену массива можно, как и во многих других языках, при помощи квадратных скобок:
PS C:\> $a = 2,3,4 PS C:\> $a[0] 2 PS C:\> $a[1] 3 PS C:\> $a[2] = 5 PS C:\> $a 2 3 5Заметьте, что мы изменили член массива, присвоив ему новое значение. Массивы powershell, также как .Net, начинаются с нуля, т.е. первый член массива всегда имеет индекс [0], а последний член [-1].Интересно, что в квадратных скобках можно указать больше одного индекса. В таком случае мы получим массив, содержащий значения этих индексов. Такой массив называется срез массива (array slice). Вот как можно получить значения первого и последнего членов:
Предыдущий пример неудобен в использовании, поскольку мы должны точно знать, что массив состоит из трех членов (именно поэтому для последнего члена был указан индекс 2). Многие языки программирования, включая powershell, позволяют обращаться к членам массива, используя отрицательные индексы. Вот, как можно изменить предыдущий пример, для получения первого и последнего члена, не зная точное количество членов:
PS C:\> $a = 2,3,4 PS C:\> $a[0,-1] 2 4Мы также можем делать срезы, указывая диапазон индексов. Вот, как можно получить пять членов массива, начиная с третьего:
PS C:\> $a = (1, 2, 3, 4, 5, 6, 7, 8) PS C:\> $a[2..6] 3 4 5 6 7Если одному из членов присвоить новый массив, существующий массив расширится. Таким образом можно вставить несколько значений в какое-то определенное место массива:
Как вы видите, исходное значение второго члена было уничтожено. Для того, чтобы сохранить это значение, можно произвести хитрую манипуляцию:
PS C:\> $a = 1,2,3 PS C:\> $a[1] = $a[1], 10, 11, 12 PS C:\> $a 1 2 10 11 12 3Так же как и со строками, с массивами можно производить операцию конкатенации, добавляя новых членов или новые массивы к существующему массиву при помощи оператора плюс:
PS C:\> $a = 1,2 PS C:\> $a = $a + 3 PS C:\> $a 1 2 3Предыдущуюю операцию можно немного упростить при помощи оператора += :
PS C:\> $a += 4 PS C:\> $a 1 2 3 4PS C:\> $a += 5,6 PS C:\> $a 1 2 3 4 5 6Очень часто приходится осуществлять поиск по массиву. Следующий пример показывает, как можно найти в массиве требуемое значение:
PS C:\> foreach ($item in (2,3,4)){if ($item -eq 3){echo "Found"}} FoundКонечно, такой способ весьма неповоротлив, так как приходится перебирать в цикле весь массив, сравнивая по очереди каждое значение. Для облегчения этой муторной операции в powershell существуют операторы -contains и -notcontains:
Эти операторы можно использовать для работы с переменными, содержащими различные типы данных:
PS C:\> (2, "some value", 4) -contains "some value" TrueСтоит быть внимательным, так как типы могут быть автоматически сконвертированны и, в результате, можно получить совсем не тот результат, которого вы ожидаете:
PS C:\> (2,3,4) -contains "3" True PS C:\> (2,3,4) -contains "3.0" TrueПонимаете, каким образом строка "3.0" превращается в число 3 и говорит True? Для того, чтобы жестко указать тип данных можно использовать команду Where-Object:
PS C:\> (2,3,4) | Where-Object {$_ -is [string] -and $_ -eq "3.0"} PS C:\> (2,"3.0",4) | Where-Object {$_ -is [string] -and $_ -eq "3.0"} 3.0слегка вольный перевод главы из книги "Pro Windows PowerShell"
yu-xuan.livejournal.com
Основы PowerShell: массивы и таблицы хеширования | Windows IT Pro/RE
Массивы и таблицы хеширования – две наиболее важных структуры данных, доступные в современных языках написания сценариев. Оболочка Windows PowerShell (http://www.windowsitpro.com/topics/powershell-scripting) поддерживает обе эти структуры. Массив, который иногда называют «коллекцией», содержит список элементов. Таблица хеширования, которую еще называют «словарем» или «массивом ассоциаций», содержит списки пар элементов. Далее в статье я покажу, как создавать массивы и таблицы хеширования, а также получать доступ к их элементам.
Создание массива
Массивы полезны в тех случаях, когда вы собираетесь хранить и просматривать список или коллекцию элементов. Один из простейших способов создать массив – использовать команду PowerShell, которая выводит более одного объекта. Например, в результате простого запуска команды Get-ChildItem будет выведен список объектов в текущем расположении. Этот список может быть сохранен в переменной. Если текущее расположение содержит более одного объекта, переменная, в которой вы сохранили список, становится массивом. Это действительно просто. Например, рассмотрим следующую команду PowerShell:
$list = Get-ChildItem $ENV:SystemRootПосле выполнения этой команды переменная $list содержит массив объектов FileInfo и DirectoryInfo.
Другой способ создать массив – указать объекты, разделив их запятыми, и присвоить их переменной:
$list = «A",»B«,"C»,«1",»2«,"3»Доступ к элементам массива
Существует три способа обращения к элементам массива.
- Использование инструкции foreach. Инструкция foreach оболочки PowerShell предоставляет удобный способ обращения к любому элементу массива. Например, чтобы вывести на экран элемент массива $list, нужно запустить команду:
- Использование команды ForEach-Object. Команда ForEach-Object рассматривает массив как входные данные из конвейера и передает каждый объект массива в блок сценария для обработки. Текущий элемент массива представлен специальной переменной $_. Чтобы вывести на экран элемент массива $list с помощью команды ForEach-Object, используйте команду:
- Применение инструкции с номером индекса. К каждому объекту (элементу) массива можно обратиться по соответствующему номеру, начиная с 0. Например, выражение $list[0] ссылается на первый элемент в массиве, выражение $list[1] ссылается на второй элемент, и так далее. Так, чтобы вывести на экран каждый член массива с помощью инструкции for и номера индекса, запустите команду:
Из этих трех подходов способ с индексами используется реже всего. Основная причина в том, что инструкция foreach и команда ForEach-Object обеспечивают более быстрое выполнение задачи.
При изучении этих трех подходов основной вопрос звучит так: в чем разница между использованием инструкции foreach и команды ForEach-Object? Разница в первую очередь в том, что при использовании инструкции foreach необходимо извлечь все элементы массива, прежде чем вы сможете получить доступ к ним. И наоборот, команда ForEach-Object использует преимущества конвейера PowerShell, позволяя получить доступ сразу к отдельному элементу.
Какой же из подходов выбрать? Ответ зависит от элементов массива. Если у вас сравнительно небольшое количество элементов массива и извлечение не займет много времени, инструкция foreach будет работать отлично. Если же у вас большой список элементов и извлечение элементов требует значительного времени (например, файлы на удаленном файловом сервере), вы, скорее всего, захотите использовать команду ForEach-Object. Также стоит подумать о применении команды Write-Progress. Если вы хотите задействовать эту команду в сценарии, чтобы информировать пользователя о ходе выполнения операции, вам придется предварительно извлечь все объекты с помощью инструкции foreach – это необходимо для расчета процента выполненной работы.
Есть еще один момент, из-за которого могут возникнуть затруднения при выборе между инструкцией foreach и командой ForEach-Object: псевдонимом команды ForEach-Object является ключевое слово foreach! Не забывайте, что при использовании выражения foreach после вертикальной черты (|) в конвейере PowerSh ell на самом деле вы вызываете команду ForEach-Object.
Другое затруднение, связанное с массивами, может проявиться, если вы знакомы с языками VBScript или JavaScript. В этих двух языках написания сценариев массивы и коллекции являются разными типами объектов. Однако в оболочке PowerShell вы можете рассматривать их как одно и то же.
Создание таблицы хеширования
Таблицы хеширования полезны в том случае, когда вам нужно хранить и извлекать объекты, обращаясь к ним по именам. Например, вы можете использовать таблицу хеширования, чтобы хранить список серверов и соответствующих им IP-адресов.
Вы можете создать таблицу хеширования путем указания имени и значения между символами @{ и }. Например, чтобы создать таблицу хеширования, которая содержит имена трех серверов и их IP-адреса, следует выполнить команду:
$hash = @{«server1» = «192.168.17.21»; «server2» = «192.168.17.22»; «server3» = «192.168.17.23»}Если вывести эту таблицу хеширования на экран (просто написать $hash в строке PowerShell и нажать клавишу ввода), вы увидите результаты, приведенные на рисунке. Заметьте, что оболочка PowerShell выводит данные столбца Name в произвольном порядке. Одна из особенностей таблицы хеширования заключается в том, что именованные элементы не имеют определенного порядка.
Рисунок. Таблица хэширования |
Доступ к элементам таблицы хеширования
Чтобы получить значение из таблицы хеширования, вы можете указать имя таблицы хеширования и далее имя элемента, значение которого вы хотите получить, заключенное в квадратные скобки. Либо вы можете поставить точку между именем таблицы и именем элемента, значение которого вы хотите получить. Например, для созданной ранее переменной $hash любая из приведенных ниже команд вернет значение 192.168.17.21:
$hash[«server1»] $hash.server1 $hash.«server1»Имейте в виду, что кавычки в команде $hash[«server1»] необходимы. Без них оболочка PowerShell не сможет получить информацию о том, каким образом обрабатывать ключ server1. Однако если имя сервера хранится в переменной (например, $serverName), вы можете применить команду:
$hash[$serverName]Некоторые команды PowerShell используют таблицы хеширования в качестве значений для параметров. Например, команда Select-Object задействует таблицы хеширования для вывода на экран вычисляемых свойств. Чтобы использовать таблицу хеширования при создании вычисляемого свойства для команды Select-Object, она должна иметь два парных значения: Name, которое задает имя вычисляемого свойства, и Expression, которое содержит блок сценариев, отвечающий за вычисление свойства. Например, возьмем команду:
Get-ChildItem $ENV:SystemRoot | select-object Name, LastWriteTime, @{Name=«Day»; Expression={$_.LastWriteTime.DayOfWeek}}В этом случае команда Select-Object выведет имя, время последней записи и день недели для каждого файла и каталога в установочной папке Windows. Как и в случае с командой ForEach-Object, специальная переменная $_ ссылается на текущий объект.
.
www.osp.ru
Ассоциативные массивы в Powershell: yu_xuan
Ассоциативные массивы - это массивы, содержашие набор пар ключ-значение, позволяющие легко и удобно отыскивать значение по ключу.Синтаксис создания ассоциативного массива в powershell подобен созданию обычных массивов; разница состоит лишь в использовании скобок (для обычных массивов используются круглые скобки, а для ассоциативных - фигурные).Для примера, рассмотрим создание ассоциативного массива, содержащего сведения об имени "Name" и адресе "Address" какого-то человека:
PS C:\> $d = @{"Name"="John"; "Address"="12 Easy St."} PS C:\> $d Name Value ---- ----- Name John Address 12 Easy St.Для создания ассоциативного массива powershell использует объект System.Collections.Hashtable:
PS C:\> $d.GetType().FullName System.Collections.HashtableПри создании ассоциативных массивов, вы можете использовать любой тип для ключей и значений:
PS C:\> $d = @{"Name"="John"; "Age"=30; ` >> "File"=(Get-Item C:\tmp\test.txt)} >> PS C:\> $d Name Value ---- ----- Name John Age 30 File C:\tmp\test.txtКак видно в предыдущем примере, в массиве $d хранится строка, int и объект FileInfo.
Для ключей также можно использовать любой тип данных. Например, у нас есть два работающих процесса MS Word и MS Outlook, мы можем объекту Process присвоить какое-то строковое значение:
PS C:\> $set = @{(Get-Process winword)="MS Word"; (Get-Process outlook)="MS Outlook"} PS C:\> $set Name Value ---- ----- System.Diagnostics.Process ... MS Outlook System.Diagnostics.Process ... MS WordМожно создать пустой ассоциативный массив при помощи конструкции @{} :
PS C:\> $empty = @{} PS C:\> $empty.GetType().FullName System.Collections.HashtableПолучить доступ к данным возможно несколькими способами. Основной - это доступ при помощи квадратных скобок, как и к обычному массиву:
PS C:\> $d = @{"Name"="John"; "Age"=30; "Address"="12 Easy St."} PS C:\> $d["Name"] JohnАссоциативные массивы могут вести себя как объекты, то есть мы можем получить доступ к значениям при помощи точечной нотации:
PS C:\> $d = @{"Name"="John"; "Age"=30; "Address"="12 Easy St."} PS C:\> $d.Name JohnТакой способ доступа ограничен тем, что ключи не должны содержать пробелов и спецсимволов. Для того, чтобы частично обойти это ограничение, можно воспользоваться кавычками, заключив в них имя ключа. Вот так можно использовать строковое значение с пробелом:
PS C:\> $d = @{"Person Name"="John"; "Age"=30; "Address"="12 Easy St."} PS C:\> $d."Person Name" JohnВ качестве ключа никто не запрещает использовать переменную:
PS C:\> $d = @{"Name"="John"; "Age"=30; "Address"="12 Easy St."} PS C:\> $property = "Name" PS C:\> $d.$property Johnи выражения:
PS C:\> $d.$($property) John PS C:\> $d.$("Na"+"me") JohnТакже как и при работе с обычными массивами, можно получить несколько значений, просто перечислив их в квадратных скобках:
PS C:\> $d = @{"Name"="John"; "Age"=30; "Address"="12 Easy St."} PS C:\> $d["Name", "Address"] John 12 Easy St.Добавление членов в ассоциативный массив возможно либо при помощи точки, либо - квадратных скобок:
PS C:\> $d.Department = "Accounting" PS C:\> $d["SSN"] = 123456789 PS C:\> $d Name Value ---- ----- Department Accounting Name John Age 30 SSN 123456789 Address 12 Easy St.Для удаления используется метод Remove() с указанием ключа:
PS C:\> $d.Remove("Age") PS C:\> $d.Remove("SSN") PS C:\> $d Name Value ---- ----- Department Accounting Name John Address 12 Easy St.Другие важные методы ассоциативных массивов, которые стоит запомнить, - это Contains() и ContainsKey(). По сути они являются синонимами и позволяют проверить массив на присутствие какого-то ключа:
PS C:\> $d.Contains("John") False PS C:\> $d.Contains("Name") True PS C:\> $d.ContainsKey("Name") TrueМетод ContainsValue() позволяет определить, существует ли искомое значение в массиве:
PS C:\> $d.ContainsValue("John") True PS C:\> $d.ContainsValue("Name") FalseВ дополнение к этому существуют свойства массивов, позволяющие отобразить все ключи и все значения, это соответственно Keys и Values:
PS C:\> $d.Keys Department Name Address PS C:\> $d.Values Accounting John 12 Easy St.Можно заменить методы ContainsKey() и ContainsValue() поиском по массиву:
PS C:\> $d.Keys -contains "Name" True PS C:\> $d.Values -contains "John" TrueНе забывайте, что -contains тихой сапой конвертирует типы данных, а методы ContainsKey() и ContainsValue() - не конвертируют.
Ну, и на последок можно упомянуть о том, что свойство Count может показать нам количество членов массива:
PS C:\> $d = @{"Name"="John"; "Age"=30; "Address"="12 Easy St."} PS C:\> $d.Count 3слегка вольный перевод главы из книги "Pro Windows PowerShell"
yu-xuan.livejournal.com
Как отсортировать массив в PowerShell
Довольно часто для хранения данных в PowerShell используются одномерные массивы вида ″ключ=значение″ (name=value). И наиболее распространенным типом массива этого вида являются hash-массивы (hashtables).
Напомню, что hash-массив представляет коллекцию пар ключ-значение, которые упорядочены по хэш-коду ключа. В PowerShell для создания hash-массивов существует упрощенный синтаксис. Для примера создадим массив и выведем его содержимое:
$array = @{a=1;b=2;c=3}
Как видно из примера, содержимое hash-массива выдается не совсем в том порядке, в котором оно было добавлено. Попробуем изменить порядок, отсортировав вывод с помощью командлета Sort-Object:
$array | Sort-Object -Name
Однако номер не прошел и порядок остался прежним. Дело в том, что в данном случае массив передается как единый объект, соответственно командлету Sort-Object сортировать просто нечего. Исправить это можно с помощью метода GetEnumerator, который извлекает каждую строку массива как отдельный объект и передает ее по конвейеру. Например:
$array.GetEnumerator() | Sort-Object Name
Таким образом, с помощью GetEnumerator нам удалось отсортировать массив по имени. Для сортировки в обратном порядке можно использовать ключ Descending:
$array.GetEnumerator() | Sort-Object Name -Descending
В принципе вопрос решен, но ради интереса поместим получившийся массив в переменную $newarray и сравним его тип с исходным. Как видите, оба массива принадлежат пространству имен System.Collections, но исходный массив относится к классу Hashtable, а новый — к DictionaryEntry. О различиях между этими классами можно почитать здесь.
Примечание. Если быть точным, то DictionaryEntry является не классом, а структурой.
Ну и раз уж речь зашла о классах, проверим, какие еще из них можно использовать для упорядочивания и сортировки массивов. Так класс SortedList представляет из себя коллекцию объектов, отсортированных по имени:
[System.Collections.SortedList]$array = @{a=1;b=2;c=3}
Класс Stack представляет неупорядоченную коллекцию объектов и работает по принципу стека, т.е. последним пришел — первым ушел:
[System.Collections.Stack]$array = @{a=1;b=2;c=3}
А класс Queue наоборот, работает по принципу очереди (первый пришел — первый ушел):
[System.Collections.Queue]$array = @{a=1;b=2;c=3}
И еще один класс OrderedDictionary, принадлежащий к пространству имен System.Collections.Specialized. Он также представляет из себя коллекцию пар ″ключ-значение″, доступ к которым можно получить по ключу или по индексу. Если не вдаваться в подробности, то этот класс представляет из себя что-то вроде хэш-массива, элементы в котором упорядочены по индексу. Класс OrderedDictionary можно использовать только с хэш-массивами. Он появился в PowerShell 3.0, и для его обозначения существует сокращенный синтаксис. Например:
$array = [ordered]@{a=1;b=2;c=3}
Обратите внимание, что название класса ставится не перед именем переменной, а перед знаком @. При попытке указать для переменной данный тип будет выдана ошибка:
[ordered]$array = @{a=1;b=2;c=3}
Такую же ошибку мы получим при попытке упорядочить уже созданный хэш-массив.
$array = @{a=1;b=2;c=3}$newarray = [ordered]$array
Таким образом, упорядочить массив можно только при его создании, сконвертировать готовый массив не получится. Впрочем при необходимости можно написать несложный скрипт для преобразования, а если лень — то воспользоваться готовым. Скрипт для конвертирования ConvertTo-OrderedDictionary можно найти в галерее Technet.
На этом все. Если вдруг тема статьи показалась интересной, то вот здесь можно узнать много нового о различных конструкциях для хранения данных (массивах, коллекциях и т.п.).
windowsnotes.ru