В дополнение Полезный ответ Джона Л.Бевана :
Get-Content
, как командлет , выводит объекты один за другим в конвейер , по мере их появления . (Обратите внимание, что конвейер задействуется при вызове командлета даже при отсутствии символа канала |
для создания цепочки множественный команды).
В этом случае выходные объекты - это отдельные строки входного текстового файла.
Если вы собираете выходные объекты конвейера , например, , присваивая его переменной , например $arrayFromFile
, или используя конвейер в контексте большего выражения с (...)
:
- PowerShell захватывает несколько выходных объектов в автоматически создаваемом массиве типа
[object[]]
,
- но если имеется только один выходной объект, этот объект захватывается как есть ( без обертка массива)
Чтобы гарантировать, что выход конвейера будет всегда массивом, PowerShell предлагает @(...)
, оператор подвыражения массива , который переносит даже один -объект вывода в массив.
Поэтому идиоматическое решение PowerShell :
$arrayFromFile = @(Get-Content C:\USER\Documents\Collections\collection.txt)
Однако часто нет необходимости гарантировать, что вы всегда получите массив , потому что PowerShell обрабатывает скаляры (одиночные значения, которые не являются коллекциями), такие же, как массивы (коллекции) во многих контекстах, например в операторах foreach
или при выводе значения, которое будет перечислено в конвейер.
TheMadTechnician указывает на то, что вы также можете использовать [Array]
для приведения / типизации вывода конвейера в качестве альтернативы @(...)
, который также создает [object[]]
массивы :
# Equivalent of the command above that additionally locks in the variable date type.
[Array] $arrayFromFile = Get-Content C:\USER\Documents\Collections\collection.txt
Используя [Array] $arrayFromFile = ...
вместо $arrayFromFile = [Array] (...)
, переменная $arrayFromFile
становится ограниченным по типу , что означает, что ее тип данных заблокирован (тогда как по умолчанию PowerShell позволяет вам изменять тип переменная в любое время).
[Array]
- это независимая от команды альтернатива типу для конкретного типа , используемому в ответе Джона, [string[]]
; вы можете использовать последний для принудительного использования единообразного типа для элементов массива, но это часто не требуется в PowerShell [1]
.
Обычные массивы PowerShell относятся к типу [object[]]
, что позволяет смешивать элементы разных типов, но любой данный элемент все же имеет определенный тип; например, даже если тип $arrayFromFile
после вышеприведенной команды равен [object[]]
, тип $arrayFromFile[0]
, т.е., например, 1-й элемент, равен [string]
(при условии, что файл содержал хотя бы 1 строку; проверьте тип с $arrayFromFile[0].GetType().Name
).
Более быстрая альтернатива: прямое использование .NET Framework
Командлеты и конвейер предлагают высокоуровневые, потенциально ограничивающие память функции, которые являются выразительными и удобными, но могут быть медленными .
Когда производительность имеет значение, необходимо прямое использование типов .NET Framework, например, [System.IO.File]
в этом случае.
$arrayFromFile = [IO.File]::ReadAllLines('C:\USER\Documents\Collections\collection.txt')
Обратите внимание, как префикс System.
может быть опущен в имени типа.
[1] Как правило, неявные преобразования типов во время выполнения PowerShell не могут обеспечить такую же безопасность типов, как, например, в C #. Например, [string[]] $a = 'one', 'two'; $a[0] = 42
делает не причиной ошибки: PowerShell просто тихо преобразует [int]
42
в строку.