Displaying hashtables
To display a hashtable that’s saved in a variable, type the variable name. By
default, a hashtables is displayed as a table with one column for keys and one
for values.
hashtables have Keys and Values properties. Use dot notation to display
all the keys or all the values.
Each key name is also a property of the hashtable, and its value is the value
of the key name property. Use the following format to display the property
values.
For example:
hashtables have a Count property that indicates the number of key-value
pairs in the hashtable.
hashtable tables aren’t arrays, so you can’t use an integer as an index
into the hashtable, but you can use a key name to index into the hashtable.
If the key is a string value, enclose the key name in quotation marks.
For example:
Handling property name collisions
If the key name collides with one of the property names of the HashTable
type, you can use the psbase intrinsic member
to access those properties. For example, if the key name is and you want
to return the collection of the HashTable keys, use this syntax:
This applies for other types which implement the
System.Collections.IDictionary interface, like OrderedDictionary.
Что выбрать для использования Select-Object или Format-Table
В предыдущих статьях рассмотрены опции, примеры и тонкости работы с Format-Table, подробности смотрите по ссылкам:
- Как в PowerShell менять набор выводимых по умолчанию данных
- Тонкая настройка вывода с Format-Table
- В PowerShell таблица не помещается на экран — как исправить (РЕШЕНО)
У обоих командлетов, Select-Object или Format-Table, имеется опция -Property, которую можно пропускать. Опция имеет общие для обоих командлетов параметры:
- Name (или Label) = `<строка>`
- Expression = `<строка>` или `<скриптовый блок>`
Благодаря этому следующие команды дают идентичный результат:
Get-PSDrive C | Format-Table @{Expression={$_.Free/1GB}} Get-PSDrive C | Select-Object @{Expression={$_.Free/1GB}}
И эти две команды выведут в точности одинаковые данные о количестве свободного и занятого дискового пространства:
Get-PSDrive C | Format-Table @{Expression={$_.Free/1GB}},@{Expression={$_.Used/1GB}} Get-PSDrive C | Select-Object @{Expression={$_.Free/1GB}},@{Expression={$_.Used/1GB}}
Следующая команда взята из статьи «Как поменять заголовок столбца в выводе PowerShell. Как поменять ширину и выравнивание в таблицах»:
Get-ChildItem | Format-Table @{Label="Режим"; Expression={$_.Mode}}, @{Label="Последняя запись в"; Expression={$_.LastWriteTime}}, @{Label="Размер"; Expression={$_.Length}}, @{Label="Имя"; Expression={$_.Name}}
В предыдущей команде заголовки всех столбцов переведены на русский.
Если Format-Table заменить на Select-Object, то команда вновь сработает:
Get-ChildItem | Select-Object @{Label="Режим"; Expression={$_.Mode}}, @{Label="Последняя запись в"; Expression={$_.LastWriteTime}}, @{Label="Размер"; Expression={$_.Length}}, @{Label="Имя"; Expression={$_.Name}}
Ещё одна команда из статьи, ссылка на которую дана выше:
Get-ChildItem | Format-Table @{Label="Режим"; Expression={$_.Mode}; Width=8}, @{Label="Последняя запись в"; Expression={$_.LastWriteTime}; Width=20}, @{Label="Размер"; Expression={$_.Length}; Width=7; Alignment="Left"}, @{Label="Имя"; Expression={$_.Name}}
Но аналогичная команда с Select-Object:
Get-ChildItem | Select-Object @{Label=»Режим»; Expression={$_.Mode}; Width=8}, @{Label=»Последняя запись в»; Expression={$_.LastWriteTime}; Width=20}, @{Label=»Размер»; Expression={$_.Length}; Width=7; Alignment=»Left»}, @{Label=»Имя»; Expression={$_.Name}}
завершилась ошибкой:
Select-Object: The Width key is not valid.
Причина ошибки в том, что для параметра -Property командлета Format-Table предусмотрены также следующие ключи, в дополнении к двум уже рассмотренным выше:
- FormatString = `<строка>`
- Width = `<int32>`
- Alignment = значением может быть Left, Center или Right
А для параметра -Property командлета Select-Object данные ключи отсутствуют. Таким образом, если вам нужно указать ширину столбцов и выравнивание в них, то используйте Format-Table вместо Select-Object.
Если вам нужно создать новое свойство объекта, также используйте Select-Object.
Массивы в Powershell: yu_xuan
Создать массив в powershell можно просто перечислив его члены через запятую. Для примера создадим небольшой массив, состоящий из чисел:
Как видно из предыдущего примера, массив имеет тип Object, то есть это означает, что членам массива может быть присвоен любой объект:
В предыдущем примере создан массив объектов, содержащий число, число двойной точности с плавающей запятой, строку и объект Process, т.е. всего четыре объекта: int, double, string, System.Diagnostics.Process instance.
Для создания массива используется довольно свободный синтаксис, однако существует формальный способ, заключающийся в использовании конструкции @() :
Для создания пустого массива можно воспользоваться следующим способом:
Для удобства массив можно создавать, указывая необходимый диапазон чисел:
Такой синтаксис чрезвычайно удобно использовать для перечисления большого набора упорядоченных чисел таких как номера портов или адреса.
При создании массивов powershell умеет распознавать вложенные массивы и превращать их в один массив:
Получить доступ к члену массива можно, как и во многих других языках, при помощи квадратных скобок:
Заметьте, что мы изменили член массива, присвоив ему новое значение. Массивы powershell, также как .Net, начинаются с нуля, т.е. первый член массива всегда имеет индекс , а последний член .Интересно, что в квадратных скобках можно указать больше одного индекса. В таком случае мы получим массив, содержащий значения этих индексов. Такой массив называется срез массива (array slice). Вот как можно получить значения первого и последнего членов:
Предыдущий пример неудобен в использовании, поскольку мы должны точно знать, что массив состоит из трех членов (именно поэтому для последнего члена был указан индекс 2). Многие языки программирования, включая powershell, позволяют обращаться к членам массива, используя отрицательные индексы. Вот, как можно изменить предыдущий пример, для получения первого и последнего члена, не зная точное количество членов:
Мы также можем делать срезы, указывая диапазон индексов. Вот, как можно получить пять членов массива, начиная с третьего:
Если одному из членов присвоить новый массив, существующий массив расширится. Таким образом можно вставить несколько значений в какое-то определенное место массива:
Как вы видите, исходное значение второго члена было уничтожено. Для того, чтобы сохранить это значение, можно произвести хитрую манипуляцию:
Так же как и со строками, с массивами можно производить операцию конкатенации, добавляя новых членов или новые массивы к существующему массиву при помощи оператора плюс:
Предыдущуюю операцию можно немного упростить при помощи оператора += :
Очень часто приходится осуществлять поиск по массиву. Следующий пример показывает, как можно найти в массиве требуемое значение:
Конечно, такой способ весьма неповоротлив, так как приходится перебирать в цикле весь массив, сравнивая по очереди каждое значение. Для облегчения этой муторной операции в powershell существуют операторы -contains и -notcontains:
Эти операторы можно использовать для работы с переменными, содержащими различные типы данных:
Стоит быть внимательным, так как типы могут быть автоматически сконвертированны и, в результате, можно получить совсем не тот результат, которого вы ожидаете:
Понимаете, каким образом строка «3.0» превращается в число 3 и говорит True? Для того, чтобы жестко указать тип данных можно использовать команду Where-Object:
слегка вольный перевод главы из книги «Pro Windows PowerShell»
Операторы
Операторы в PowerShell также эффективны для массивов. Некоторые из них работают несколько иначе.
-join
Оператор является самым очевидным примером, поэтому давайте рассмотрим его первым. Мне нравится оператор , я его часто использую. Он объединяет все элементы в массиве с помощью заданного символа или строки.
В операторе мне особенно нравится то, что он обрабатывает единичные элементы.
Я использую его для ведения журнала и подробных сообщений.
-join $array
Вот еще один полезный прием, о котором мне рассказал Ли Дейли. Если нужно объединить все без использования разделителя, вместо этого:
Можно использовать с массивом в качестве параметра без префикса. Этот пример наглядно демонстрирует то, о чем я говорил.
-replace и -split
Другие операторы, такие как и , выполняются для каждого элемента в массиве. Не скажу, что я их когда-нибудь таким образом использовал, но вот пример этого.
-in
Если одно значение, которое вам нужно проверить, совпадает с одним или несколькими значениями, можно использовать оператор . Значение должно быть в левой, а массив — в правой части оператора.
Такой способ может оказаться дорогостоящим, если список достаточно велик. Я часто использую шаблон регулярного выражения, если проверяется большое количество значений.
-eq и -ne
Равенство и массивы могут оказаться достаточно сложными. Если массив располагается в левой части, выполняется сравнение всех элементов. Вместо возврата возвращается совпадающий объект.
Если используется оператор , вы получаете все значения, которые не равны имеющемуся.
При использовании в операторе возвращается значение . Если значение не возвращается, то речь о значении . Оба этих оператора оцениваются как .
Я еще вернусь к этому вопросу позднее, когда мы будем говорить о тестировании .
-match
Оператор пытается сопоставить все элементы в коллекции.
При использовании с одним значением специальная переменная заполняется сведениями о соответствии. Этого не происходит, если массив обрабатывается таким образом.
Этот же подход можно использовать в случае с .
Я подробно расскажу о переменных , и в другой публикации под названием Множество способов использования регулярных выражений (Множество способов использования регулярных выражений).
$null или empty
Проверка на наличие или пустых массивов может быть непростой задачей. Далее описаны самые распространенные проблемы, связанные с массивами.
На первый взгляд этот оператор выглядит вполне работоспособным.
Однако я только что рассказал, как проверяет каждый элемент в массиве. Таким образом, у нас может быть массив из нескольких элементов с одним значением $null и результатом вычисления будет
Именно поэтому рекомендуется размещать в левой части оператора. Благодаря этому сценарий выполняется без проблем.
Массив не равен пустому массиву. Если вы уверены, что у вас есть массив, проверьте количество объектов в нем. Если это массив , число объектов равно .
Однако есть еще одна сложность, которую нужно учитывать в этом случае. Можно использовать даже при наличии одного объекта, если только этот объект не является . Эта ошибка исправлена в PowerShell 6.1.
Это хорошая новость, однако многие люди по-прежнему используют версию 5.1, так что им стоит иметь в виду указанную ошибку.
Если вы по-прежнему используете PowerShell 5.1, можно перенести объект в массив перед проверкой количества объектов, чтобы получить точное число.
Чтобы безопасно воспроизвести этот сценарий, проверьте , а затем проверьте число объектов.
Недавно кто-то спрашивал, как проверить, соответствует ли каждое значение в массиве заданному значению.
Пользователь Reddit /u/bis предложил это разумное решение, которое проверяет наличие некорректных значений, а затем инвертирует результат.
Имена переменных, включающие специальные символы
Имена переменных начинаются со знака доллара () и могут включать буквенно-цифровые символы и специальные символы. Длина имени переменной ограничена только доступной памятью.
Рекомендуется, чтобы имена переменных включали только буквенно-цифровые символы и символ подчеркивания (). Имена переменных, включающие пробелы и другие специальные символы, трудно использовать и следует избегать.
Буквенно-цифровые имена переменных могут содержать следующие символы:
- Символы Юникода из этих категорий: Lu, Ll, Lt, Lm, Lo или Nd.
- Символ подчеркивания ().
- Знак вопроса () символ.
В следующем списке содержатся описания категорий Юникода. Дополнительные сведения см. в разделе UnicodeCategory.
- Lu — UppercaseLetter
- Ll — LowercaseLetter
- Lt — TitlecaseLetter
- Lm — ModifierLetter
- Lo — OtherLetter
- Nd — DecimalDigitNumber
Чтобы создать или отобразить имя переменной, включающее пробелы или специальные символы, заключите имя переменной с фигурными скобками () символами.
Фигурные скобки направляют PowerShell для интерпретации символов имени переменной как литералы.
Имена специальных переменных символов могут содержать следующие символы:
- Любой символ Юникода со следующими исключениями:
- Закрывающая фигурная скобка () (U+007D).
- Символ обратной черты () (U+0060). Обратная черта используется для экранирования символов Юникода, поэтому они обрабатываются как литералы.
PowerShell имеет зарезервированные переменные, такие как , и содержащие буквенно-цифровые и специальные символы. Дополнительные сведения см. в статье about_Automatic_Variables.
Например, следующая команда создает переменную с именем . Фигурные скобки () необходимы, так как имя переменной включает специальный символ дефиса ().
Следующая команда получает дочерние элементы в каталоге, представленном переменной среды.
Чтобы ссылаться на имя переменной, включающую фигурные скобки, заключите имя переменной в фигурные скобки и используйте символ обратного ввода для экранирования фигурных скобок. Например, чтобы создать переменную именованного типа:
Добавление в массивы
На этом этапе вас начинает интересовать, как добавить элементы в массив. Собственно говоря, никак. Массив имеет фиксированный размер в памяти. Если необходимо увеличить массив или добавить в него один элемент, то в этом случае необходимо создать новый массив и скопировать в него все значения из старого. На первый взгляд это требует значительных усилий, однако PowerShell значительно упрощает создание нового массива. В PowerShell реализован оператор сложения () для массивов.
Примечание
В PowerShell не реализована операция вычитания. Если требуется гибкая альтернатива массиву, необходимо использовать .
Сложение массивов
Для создания нового массива можно использовать оператор сложения. Итак, дано два массива:
Мы можем сложить их вместе, чтобы получить новый массив.
Плюс равно (+=)
Мы можем создать новый массив и добавить в него элемент следующим образом:
Просто помните, что каждый раз, когда вы используете , выполняется дублирование и создание нового массива. Это не проблема, если речь идет о небольших наборах данных, но масштабирование в этом случае выполняется очень ограниченно.
Назначение конвейера
Можно назначить результаты любого конвейера для добавления в любую переменную. Она будет считаться массивом, если содержит несколько элементов.
Обычно если мы говорим об использовании конвейера, мы подразумеваем типичные однострочные сценарии PowerShell. Можно использовать конвейер с операторами и другими циклами. Таким образом, вместо добавления элементов в массив в цикле можно поместить элементы в конвейер.
Типы массивов
По умолчанию массив в PowerShell создается как тип . Благодаря этому он может содержать любые типы объектов и значений. Это возможно, поскольку все наследуется из типа .
Строго типизированные массивы
Массив любого типа можно создать с помощью сходного синтаксиса. Если вы создаете строго типизированный массив, он может содержать только значения или объекты заданного типа.
ArrayList
Добавление элементов в массив накладывает самые серьезные ограничения, однако существует ряд других коллекций, которые можно использовать для решения этой проблемы.
Как правило, если нам нужен массив, поддерживающий более быструю работу, мы в первую очередь вспоминаем о . Он выступает в качестве массива объектов везде, где это необходимо, и при этом поддерживает быстрое добавление элементов.
Мы создаем и добавляем в него элементы следующим образом.
Для получения этого типа вызывается .NET. В этом случае для его создания используется конструктор по умолчанию. Затем вызывается метод , чтобы добавить в него элемент.
Причина, по которой я использую в начале строки, заключается в подавлении кода возврата. Некоторые вызовы .NET выполняют такую функцию, и в результате могут быт получены неожиданные выходные данные.
Если единственными данными в массиве являются строки, ознакомьтесь также с использованием StringBuilder. Это практически то же самое, но некоторые методы предназначены только для работы со строками. специально предназначен для повышения производительности.
Обычно пользователи переходят на с массивов. Однако это наследие тех времен, когда в C# еще не была предусмотрена универсальная поддержка. От отказываются в пользу универсального
Универсальный список
Универсальный тип — это особый тип в C#, который определяет обобщенный класс, при этом пользователь указывает типы данных, которые используются в процессе создания. Поэтому если требуется список чисел или строк, необходимо определить, что требуется список типов или .
Список для строк создается следующим образом.
Так же создается список чисел.
Можно привести существующий массив к списку следующим образом, не создавая сначала объект:
Синтаксис можно сократить с помощью оператора в PowerShell 5 и более поздних версиях. Оператор должен быть первой строкой сценария. Объявляя пространство имен, PowerShell позволяет исключить из него типы данных при ссылке на них.
Это позволяет сделать гораздо более удобным.
Вам доступен аналогичный метод . В отличие от ArrayList метод не возвращает значение, поэтому для него не нужно выполнять .
Кроме того, мы по-прежнему можем получить доступ к таким элементам, как другие массивы.
List
Можно получить список любого типа, но, если вам неизвестен тип объектов, в качестве контейнера для них можно использовать .
Remove()
Как , так и универсальные поддерживают удаление элементов из коллекции.
При работе с типами значений из списка удаляется первый из типов. Его можно вызвать снова, чтобы еще раз удалить это значение. Если используются ссылочные типы, необходимо предоставить объект, который требуется удалить.
Метод Remove возвращает , если удалось найти и удалить элемент из коллекции.
Можно использовать также множество других коллекций, однако эти оптимальны в качестве замены массивам.
Если вам интересно узнать больше о других вариантах, взгляните на Gist, собранный Марком Краусом.
Keys and Values
Hashtables aren’t structures exclude to PowerShell, you can find them in many languages and places. The thing that differentiates them from traditional arrays and lists is that they’re based on keys and values. If you’re familiar with dictionary data types, the hashtable is one of them. Each item in a hashtable has a unique key which corresponds to a value. This means you can’t have the same item more than once, at least not with the exact same key.
Creating Hashtables
If we think back to when we explored arrays we may remember that we could create arrays with a simple syntax. Hashtables have a very similar syntax for the most simple way of creating them.
The difference to creating arrays is that you use braces, curly brackets or whichever name you prefer, instead of parentheses to create hashtables. That’s a shorthand way of creating one, but as with many data types there are a few more ways.
I prefer the first way, I think it’s the simplest and most readable when it comes to declaring values directly.
Notice the semicolon to separate the items without a line break.
Setting Values
As we can see, we’re able to quickly set values when creating the hashtable, but what if we want to add or modify items after it’s created?
I wouldn’t use the last one anywhere because of readability, but lean towards the second one as it removes any confusion about what type of object we’re working with.
Something good to know is that it’s not only a choice of style or preference between the three, behind them lurks a large performance difference.
If you run the three examples in your console you will notice that the first one takes way longer to run. For me the last two take about 50 milliseconds in PowerShell 7, while the first one that uses the property-style of setting the value runs for almost 8 seconds!
If you happen to handle a lot of data it’s always good to keep performance differences in mind, something we also discussed during our earlier parts of the PowerShell Collections series.
Accessing Values
To get the values from a hashtable we can use a similar syntax as when setting values.
We can also access several values at once if we want!
Removing Values
Just as we may want to add values after creation, sometimes we also want to remove items from the hashtable.
To remove the value we always need to provide the key.
Finding Keys or Values
If we’re not sure if the key exists, we can use methods provided by the hashtable type. We can also use one of the methods to see if a specific value exists.
All of them return either true or false, and something to note is that works in the same way as with the difference being only the name.
Copying Hashtables
The hashtable is a reference type, which is something we need to be aware of when trying to copy one.
The behavior above differs from copying for example numbers or other types that we may be used to, where would only still contain my name and not the blog item. The new hashtable we copied to in our second line is actually only a reference to the original one, and changing either of them will change both. To copy a hashtable we can use the method.
This isn’t unusual when working with lists or dictionaries in .NET, so keep it in mind if you decide to explore other collection types that aren’t as common in PowerShell.
Another way of copying a hashtable in PowerShell is to combine it with a new empty hashtable, though I would say it’s up for debate whether or not it improves readability. As for performance it doesn’t seem to be any discernable difference at least.
Все занятные вещи
Упорядоченные хэш-таблицы
По умолчанию хэш-таблицы не упорядочиваются (не сортируются). В традиционном контексте порядок не имеет значения, если для доступа к значениям всегда используется ключ. Возможно, вам потребуется сохранить ранее определенный порядок свойств. К счастью, это можно сделать с использованием ключевого слова .
Теперь при перечислении ключи и значения сохраняют этот порядок.
Строковые хэш-таблицы
При определении хэш-таблицы в одной строке можно разделять пары «ключ-значение» точкой с запятой.
Это удобно, если вы создаете их в канале.
Настраиваемые выражения в общих командах конвейера
Существует несколько командлетов, которые поддерживают использование хэш-таблиц для создания настраиваемых или вычисляемых свойств. Как правило, они используются в и . Хэш-таблицы используют специальный синтаксис, который в развернутом виде выглядит следующим образом.
Командлет помечает этот столбец как . — это блок выполняемого сценария, где представляет значение объекта в канале. Далее рассматривается действие сценария.
Я поместил его в переменную, однако его можно определить как строковый и сократить до и до в процессе работы над ним.
Лично мне не нравится, что команды выполняются долго, и зачастую проявляются нежелательные последствия. Лучше я создам новую хэш-таблицу или со всеми нужными полями и свойствами вместо того, чтобы использовать этот метод со сценариями. Однако там содержится большой объем кода, который выполняет эти задачи, и вам следует помнить об этом. Я имею в виду последующее создание .
Настраиваемое выражение сортировки
Можно легко отсортировать коллекцию, если объекты содержат данные, которые вы хотите использовать как критерий сортировки. Можно либо добавить данные в объект перед сортировкой, либо создать настраиваемое выражение для .
В этом примере я выберу список пользователей и использую специальный командлет, чтобы получить дополнительную информацию исключительно в целях сортировки.
Сортировка списка хэш-таблиц
При наличии списка хэш-таблиц, которые нужно отсортировать, выясняется, что не обрабатывает ключи как свойства. Эту проблему можно решить с помощью настраиваемых выражений сортировки.