Поделиться через


about_Arrays

Краткое описание

Описывает массивы, которые являются структурами данных, предназначенными для хранения коллекций элементов.

Подробное описание

Массив — это структура данных, предназначенная для хранения коллекции элементов. Элементы могут быть одинаковыми или разными типами.

Начиная с Windows PowerShell 3.0 коллекция из нуля или одного объекта имеет некоторые свойства массивов.

Создание и инициализация массива

Чтобы создать и инициализировать массив, назначьте несколько значений переменной. Значения, хранящиеся в массиве, разделены запятыми и отделены от имени переменной оператором назначения (=).

Например, чтобы создать массив с именем $A , содержащий семь числовых (целочисленных) значений 22, 5, 10, 8, 12, 9 и 80, введите:

$A = 22,5,10,8,12,9,80

Запятую можно также использовать для инициализации массива отдельных элементов, поместив запятую перед одним элементом.

Например, чтобы создать один массив элементов с именем $B , содержащим одно значение 7, введите:

$B = ,7

Вы также можете создать и инициализировать массив с помощью оператора диапазона (..). В следующем примере создается массив, содержащий значения 5–8.

$C = 5..8

В результате $C содержит четыре значения: 5, 6, 7 и 8.

Если тип данных не указан, PowerShell создает каждый массив в виде массива объектов (System.Object[]). Чтобы определить тип данных массива, используйте GetType() этот метод. Например:

$A.GetType()

Чтобы создать строго типизированный массив, то есть массив, который может содержать только значения определенного типа, приведение переменной в качестве типа массива, например string[], long[] или int32[]. Чтобы привести массив, предшествуйте имени переменной с типом массива, заключенным в квадратные скобки. Например:

[int32[]]$ia = 1500, 2230, 3350, 4000

В результате $ia массив может содержать только целые числа.

Вы можете создать массивы, приводимые к любому поддерживаемому типу в .NET. Например, объекты, извлекаемые Get-Process для представления процессов, относятся к типу System.Diagnostics.Process . Чтобы создать строго типизированный массив объектов процесса, введите следующую команду:

[Diagnostics.Process[]]$zz = Get-Process

Оператор вложенных выражений массива

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

Синтаксис оператора массива выглядит следующим образом:

@( ... )

Оператор массива можно использовать для создания массива с нулевым или одним объектом. Например:

$a = @("Hello World")
$a.Count
1
$b = @()
$b.Count
0

Оператор массива полезен в сценариях при получении объектов, но не знаю, сколько ожидается. Например:

$p = @(Get-Process Notepad)

Дополнительные сведения о операторе вложенных выражений массива см. в about_Operators.

Доступ и использование элементов массива

Чтение массива

Вы можете ссылаться на массив, используя его имя переменной. Чтобы отобразить все элементы в массиве, вызовите имя массива. Например, $a это массив чисел от 0 до 9:

$a
0
1
2
3
4
5
6
7
8
9

Вы можете ссылаться на элементы массива с помощью индекса. Заключите номер индекса в квадратные скобки. Значения индекса начинаются с 0. Например, чтобы отобразить first элемент в массиве $a , введите:

$a[0]
0

Чтобы отобразить третий элемент в массиве, введите следующее $a :

$a[2]
2

Часть массива можно получить с помощью оператора диапазона для индекса. Например, чтобы получить второй до пятых элементов массива, введите следующее:

$a[1..4]
1
2
3
4

Отрицательные count числа из конца массива. Например, -1 ссылается на last элемент массива. Чтобы отобразить last три элемента массива, в порядке возрастания индекса введите:

$a = 0 .. 9
$a[-3..-1]
7
8
9

Если вы вводите отрицательные индексы в порядке убывания, выходные данные изменяются.

$a = 0 .. 9
$a[-1..-3]
9
8
7

Однако будьте осторожны при использовании этой нотации. Нотация циклов от конечной границы до начала массива.

$a = 0 .. 9
$a[2..-2]
2
1
0
9
8

Кроме того, одна из распространенных ошибок заключается в том, чтобы предположить $a[0..-2] , что относится ко всем элементам массива, кроме last одного. Он относится к firstlastэлементам , а также к элементам второго типаlast в массиве.

Оператор plus (+) можно использовать для объединения диапазонов со списком элементов в массиве. Например, чтобы отобразить элементы в позициях индекса 0, 2 и 4–6, введите:

$a = 0 .. 9
$a[0,2+4..6]
0
2
4
5
6

Кроме того, для перечисления нескольких диапазонов и отдельных элементов можно использовать оператор plus. Например, чтобы вывести список элементов нулю до двух, четырех до шести, а элемент в восьмом позициальном типе:

$a = 0..9
$a[+0..2+4..6+8]
0
1
2
4
5
6
8

Итерации по элементам массива

Можно также использовать конструкции циклического цикла, такие как foreach, forи while циклы, для ссылки на элементы в массиве. Например, чтобы использовать foreach цикл для отображения элементов в массиве $a , введите:

$a = 0..9
foreach ($element in $a) {
  $element
}
0
1
2
3
4
5
6
7
8
9

Цикл foreach выполняет итерацию по массиву и возвращает каждое значение в массиве until , достигающее конца массива.

Цикл for полезен при добавочных счетчиках при проверке элементов в массиве. Например, чтобы использовать for цикл для возврата каждого другого значения в массиве, введите:

$a = 0..9
for ($i = 0; $i -le ($a.length - 1); $i += 2) {
  $a[$i]
}
0
2
4
6
8

Вы можете использовать while цикл для отображения элементов в массиве until определенного условия больше не имеет значения true. Например, чтобы отобразить элементы в массиве $a , а индекс массива меньше 4, введите:

$a = 0..9
$i=0
while($i -lt 4) {
  $a[$i]
  $i++
}
0
1
2
3

Свойства массивов

Count или Length или LongLength

Чтобы определить, сколько элементов находится в массиве, используйте Length свойство или его Count псевдоним. Longlength полезно, если массив содержит более 2 147 483 647 элементов.

$a = 0..9
$a.Count
$a.Length
10
10

Rank

Возвращает число измерений в массиве. Большинство массивов в PowerShell имеют только одно измерение. Даже если вы считаете, что вы создаете многомерный массив, как показано в следующем примере:

$a = @(
  @(0,1),
  @("b", "c"),
  @(Get-Process)
)

"`$a rank: $($a.Rank)"
"`$a length: $($a.Length)"
"`$a[2] length: $($a[2].Length)"
"Process `$a[2][1]: $($a[2][1].ProcessName)"

В этом примере создается одномерный массив, содержащий другие массивы. Это также называется массивом с замеченным элементом. Свойство Rank доказало, что это одномерное. Чтобы получить доступ к элементам в массиве, индексы должны находиться в отдельных квадратных скобках ([]).

$a rank: 1
$a length: 3
$a[2] length: 348
Process $a[2][1]: AcroRd32

Многомерные массивы хранятся в основном порядке строк. В следующем примере показано, как создать действительно многомерный массив.

[string[,]]$rank2 = [string[,]]::New(3,2)
$rank2.rank
$rank2.Length
$rank2[0,0] = 'a'
$rank2[0,1] = 'b'
$rank2[1,0] = 'c'
$rank2[1,1] = 'd'
$rank2[2,0] = 'e'
$rank2[2,1] = 'f'
$rank2[1,1]
2
6
d

Чтобы получить доступ к элементам в многомерном массиве, разделите индексы с помощью запятой (,) в одном наборе квадратных скобок ([]).

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

$a = "red",$true
$b = (New-Object 'int[,]' 2,2)
$b[0,0] = 10
$b[0,1] = 20
$b[1,0] = 30
$b[1,1] = 40
$c = $a + $b
$a.GetType().Name
$b.GetType().Name
$c.GetType().Name
$c

Выходные данные показывают, что это 1-мерный массив, $c содержащий элементы из $a $b и в основном порядке строк.

Object[]
Int32[,]
Object[]
red
True
10
20
30
40

Методы массивов

Clear

Задает все значения default элементов значением типа элемента массива. Метод Clear() не сбрасывает размер массива.

В следующем примере $a представлен массив объектов.

$a = 1, 2, 3
$a.Clear()
$a | % { $null -eq $_ }
True
True
True

В этом примере $intA явно типизированный для хранения целых чисел.

[int[]] $intA = 1, 2, 3
$intA.Clear()
$intA
0
0
0

ForEach()

Позволяет выполнять итерацию по всем элементам массива и выполнять определенную операцию для каждого элемента массива.

Метод ForEach() имеет несколько перегрузок, выполняющих различные операции.

ForEach(scriptblock expression)
ForEach(scriptblock expression, object[] arguments)
ForEach(type convertToType)
ForEach(string propertyName)
ForEach(string propertyName, object[] newValue)
ForEach(string methodName)
ForEach(string methodName, object[] arguments)

ForEach(выражение scriptblock)

ForEach(выражение scriptblock, object[] аргументы)

Этот метод был добавлен в PowerShell версии 4.

Примечание.

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

В следующем примере показано, как использовать ForEach() метод. В этом случае намерение состоит в создании квадратного значения элементов в массиве.

$a = @(0 .. 3)
$a.ForEach({ $_ * $_})
0
1
4
9

Как и параметр ForEach-ObjectArgumentList, arguments параметр позволяет передавать массив аргументов в блок скрипта, настроенный для их принятия.

Дополнительные сведения о поведении ArgumentList см. в about_Splatting.

ForEach(тип convertToType)

Метод можно использовать для приведения элементов к другому типу. В ForEach() следующем примере показано, как преобразовать список строковых дат в [DateTime] тип.

("1/1/2017", "2/1/2017", "3/1/2017").ForEach([datetime])

Sunday, January 1, 2017 12:00:00 AM
Wednesday, February 1, 2017 12:00:00 AM
Wednesday, March 1, 2017 12:00:00 AM

ForEach(string propertyName)

ForEach(string propertyName, object[] newValue)

Метод ForEach() также можно использовать для извлечения или задания значений свойств для каждого элемента в коллекции.

# Set all LastAccessTime properties of files to the current date.
(dir 'C:\Temp').ForEach('LastAccessTime', (Get-Date))
# View the newly set LastAccessTime of all items, and find Unique entries.
(dir 'C:\Temp').ForEach('LastAccessTime') | Get-Unique
Wednesday, June 20, 2018 9:21:57 AM

ForEach(string methodName)

ForEach(string methodName, object[] аргументы)

Наконец, ForEach() методы можно использовать для выполнения метода для каждого элемента в коллекции.

("one", "two", "three").ForEach("ToUpper")
ONE
TWO
THREE

Как и параметр ForEach-ObjectArgumentList, arguments параметр позволяет передавать массив значений в блок скрипта, настроенный для их принятия.

Примечание.

Начиная с Windows PowerShell 3.0, извлекая свойства и выполняя методы для каждого элемента в коллекции, также можно выполнить с помощью методов скалярных объектов и коллекций. Дополнительные сведения см. здесь about_Methods.

Where()

Позволяет фильтровать или выбирать элементы массива. Скрипт должен иметь значение, отличное от нуля (0), $false пустой строки или $null элемента, отображаемого Where()после него. Дополнительные сведения о логическое вычисление см. в about_Booleans.

Для метода существует одно определение Where() .

Where(scriptblock expression[, WhereOperatorSelectionMode mode
                            [, int numberToReturn]])

Примечание.

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

Это Expression блок скрипта, необходимый для фильтрации, mode необязательный аргумент позволяет использовать дополнительные возможности выбора, а numberToReturn необязательный аргумент позволяет ограничить количество возвращаемых элементов из фильтра.

Значение должно быть значением перечисления mode WhereOperatorSelectionMode:

  • Default (0) — возврат всех элементов
  • First (1) — возврат first элемента
  • Last (2) — возврат last элемента
  • SkipUntil (3) — условие пропуска элементов until имеет значение true, возвращает все остальные элементы (включая first элемент, для которого условие имеет значение true).
  • Until (4) — возвращает условие "Все элементы until " true
  • Split (5) — возврат массива двух элементов
    • Элемент first содержит соответствующие элементы
    • Второй элемент содержит оставшиеся элементы

В следующем примере показано, как выбрать все нечетные числа из массива.

(0..9).Where{ $_ % 2 }
1
3
5
7
9

В следующем примере показано, как выбрать все непустые строки.

('hi', '', 'there').Where{ $_ }
hi
there

Default

Режим Default фильтрует элементы с помощью скриптблока Expression .

Если задано numberToReturn значение, оно указывает максимальное количество возвращаемых элементов.

# Get the zip files in the current users profile, sorted by LastAccessTime
$Zips = dir $env:userprofile -Recurse '*.zip' | Sort-Object LastAccessTime
# Get the least accessed file over 100MB
$Zips.Where({$_.Length -gt 100MB}, 'Default', 1)

Примечание.

Как Default режим, так и First режим возвращают first элементы (numberToReturn) и могут использоваться взаимозаменяемо.

Last

$h = (Get-Date).AddHours(-1)
$logs = dir 'C:\' -Recurse '*.log' | Sort-Object CreationTime
# Find the last 5 log files created in the past hour
$logs.Where({$_.CreationTime -gt $h}, 'Last', 5)

SkipUntil

Режим SkipUntil пропускает все объекты в коллекции until , объект передает фильтр выражения блока скрипта. Затем он возвращает все оставшиеся элементы коллекции без тестирования. Тестируется только один проходящий элемент.

Это означает, что возвращаемая коллекция содержит как передача, так и непередаваемые элементы, которые не были протестированы.

Количество возвращаемых элементов может быть ограничено путем передачи значения аргументу numberToReturn .

$computers = "Server01", "Server02", "Server03", "localhost", "Server04"
# Find the first available online server.
$computers.Where({ Test-Connection $_ }, 'SkipUntil', 1)
localhost

Until

Режим Until инвертирует SkipUntil режим. Он возвращает ВСЕ элементы в коллекции until , элемент передает выражение блока скрипта. После передачи выражения Where() scriptblock метод останавливает обработку элементов.

Это означает, что first набор элементов, не проходящих из Where() метода. После прохождения одного элемента остальные не проверяются или возвращаются.

Количество возвращаемых элементов может быть ограничено путем передачи значения аргументу numberToReturn .

# Retrieve the first set of numbers less than or equal to 10.
(1..50).Where({$_ -gt 10}, 'Until')
# This would perform the same operation.
(1..50).Where({$_ -le 10})
1
2
3
4
5
6
7
8
9
10

Примечание.

Оба Until и SkipUntil работают в локальной среде НЕ тестируют пакет элементов.

Untilвозвращает элементы ДО firstPASS. SkipUntilвозвращает все элементы ПОСЛЕ прохожденияfirst, включая передаваемый first элемент.

Split

Режим Split разделяет элементы коллекции или группирует их на две отдельные коллекции. Те, которые передают выражение scriptblock, и те, которые не выполняются.

numberToReturn Если задано, first коллекция содержит передаваемые элементы, а не превышает указанное значение.

Остальные объекты, даже те, которые передают фильтр выражений, возвращаются во второй коллекции.

$running, $stopped = (Get-Service).Where({$_.Status -eq 'Running'}, 'Split')
$running
Status   Name               DisplayName
------   ----               -----------
Running  Appinfo            Application Information
Running  AudioEndpointBu... Windows Audio Endpoint Builder
Running  Audiosrv           Windows Audio
...
$stopped
Status   Name               DisplayName
------   ----               -----------
Stopped  AJRouter           AllJoyn Router Service
Stopped  ALG                Application Layer Gateway Service
Stopped  AppIDSvc           Application Identity
...

Примечание.

Where() Оба ForEach() метода являются встроенными элементами. Дополнительные сведения о встроенных элементах см. в этой статье.

Получение элементов массива

Чтобы получить свойства и методы массива, такие как Length свойство и метод SetValue , используйте параметр InputObject командлета Get-Member .

При отправке массива Get-Memberв PowerShell отправляет элементы по одному за раз и Get-Member возвращает тип каждого элемента в массиве (игнорируя повторяющиеся).

При использовании параметра Get-Member InputObject возвращает элементы массива.

Например, следующая команда получает члены переменной массива $a .

Get-Member -InputObject $a

Вы также можете получить члены массива, введя запятую (,) перед значением, которое будет передано командлету Get-Member . Запятая делает массив вторым элементом в массиве массивов. PowerShell передает массивы по одному и Get-Member возвращает элементы массива. Как и в следующих двух примерах.

,$a | Get-Member

,(1,2,3) | Get-Member

Управление массивом

Элементы в массиве можно изменить, добавить элемент в массив и объединить значения из двух массивов в третий массив.

Чтобы изменить значение определенного элемента в массиве, укажите имя массива и индекс элемента, который требуется изменить, а затем используйте оператор присваивания (=) для указания нового значения элемента. Например, чтобы изменить значение второго элемента в массиве $a (позиция индекса 1) на 10, введите:

$a[1] = 10

Для изменения значения можно также использовать метод SetValue массива. Следующий пример изменяет второе значение (позицию индекса 1) массива $a на 500:

$a.SetValue(500,1)

Оператор можно использовать += для добавления элемента в массив. В следующем примере показано, как добавить элемент в $a массив.

$a = @(0..4)
$a += 5

Примечание.

При использовании += оператора PowerShell фактически создает новый массив со значениями исходного массива и добавленным значением. Это может привести к проблемам с производительностью, если операция повторяется несколько раз или размер массива слишком велик.

Несложно удалить элементы из массива, но можно создать новый массив, содержащий только выбранные элементы существующего массива. Например, чтобы создать $t массив со всеми элементами в $a массиве, за исключением значения в позиции индекса 2, введите:

$t = $a[0,1 + 3..($a.length - 1)]

Чтобы объединить два массива в один массив, используйте оператор plus (+). В следующем примере создаются два массива, объединяются и отображаются итоговые объединенные массивы.

$x = 1,3
$y = 5,9
$z = $x + $y

В результате массив $z содержит 1, 3, 5 и 9.

Чтобы удалить массив, назначьте значение $null массиву. Следующая команда удаляет массив в переменной $a .

$a = $null

Можно также использовать Remove-Item командлет, но назначение значения $null выполняется быстрее, особенно для больших массивов.

Массивы из нуля или одного

Начиная с Windows PowerShell 3.0 коллекция из нуля или одного объекта имеет Count свойства и Length свойства. Кроме того, можно индексировать массив одного объекта. Эта функция помогает избежать ошибок сценариев, возникающих при выполнении команды, ожидающей, что коллекция получает менее двух элементов.

В следующем примере показано, что переменная, содержащая объекты, не имеет Count значения Length 0 и 0.

PS> $a = $null
PS> $a.Count
0
PS> $a.Length
0

В следующем примере показано, что переменная, содержащая один объект, имеет Count значение Length 1. Можно также использовать индексирование массивов для доступа к значению объекта.

PS> $a = 4
PS> $a.Count
1
PS> $a.Length
1
PS> $a[0]
4
PS> $a[-1]
4

При выполнении команды, которая может возвращать коллекцию или один объект, можно использовать индексирование массивов для доступа к значению объекта без необходимости проверять Count Length или свойства. Однако если результатом является один объект (singleton), а этот объект имеет Count или Length свойство, значение этих свойств принадлежит одному объекту и не представляет количество элементов в коллекции.

В следующем примере команда возвращает один строковый объект. Эта Length строка имеет значение 4.

PS> $result = 'one','two','three','four' | Where-Object {$_ -like 'f*'}
PS> $result.GetType().FullName
System.String
PS> $result
four
PS> $result.Count
1
PS❯ $result.Length
4

Если вы хотите $result быть массивом строк, необходимо объявить переменную в виде массива.

В этом примере $result представляет собой массив строк. И Count массив имеет 1значение , а Length first элемент имеет значение 4.Length

PS> [string[]]$result = 'one','two','three','four' |
    Where-Object {$_ -like 'f*'}
PS> $result.GetType().FullName
System.String[]
PS> $result
four
PS> $result.Count
1
PS> $result.Length
1
PS> $result[0].Length
4

Поддержка индексирования системы.Tuple Объектов

PowerShell 6.1 добавила поддержку индексированного доступа Tuple к объектам, аналогичным массивам. Например:

PS> $tuple = [Tuple]::Create(1, 'test')
PS> $tuple[0]
1
PS> $tuple[1]
test
PS> $tuple[0..1]
1
test
PS> $tuple[-1]
test

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

Дополнительные сведения см. в разделе System.Tuple.

Индексирование типов .NET, реализующих IDictionary<TKey, TValue>

PowerShell не вызывает истинный индексатор типа для типов, реализующих универсальный IDictionary<TKey, TValue> интерфейс. Вместо этого при указании ключа PowerShell проверяет наличие ключа, TryGetValue()который возвращает $null , когда ключ не существует.

В отличие от этого, если вызвать истинный индексатор типа, Item(<key>)метод создает исключение, если ключ не существует.

В следующем примере демонстрируется это различие.

PS> [Collections.Generic.Dictionary[string, int]]::new()['nosuchkey']
# No output ($null)

PS> [Collections.Generic.Dictionary[string, int]]::new().Item('nosuchkey')
GetValueInvocationException: Exception getting "Item": "The given key 'nosuchkey'
 was not present in the dictionary."

Перечисление доступа к членам

Начиная с PowerShell 3.0 при использовании оператора доступа к члену для доступа к элементу, который не существует в коллекции списков, PowerShell автоматически перечисляет элементы в коллекции и пытается получить доступ к указанному элементу на каждом элементе. Дополнительные сведения см. в разделе about_Member-Access_Enumeration.

Примеры

В следующем примере создаются два новых файла и хранятся полученные объекты в переменной $filesмассива. Так как объект массива не имеет члена LastWriteTime, значение LastWriteTime возвращается для каждого элемента в массиве.

$files = (New-Item -Type File -Force '/temp/t1.txt'),
         (New-Item -Force -Type File '/temp/t2.txt')
$files.LastWriteTime
Friday, June 25, 2021 1:21:17 PM
Friday, June 25, 2021 1:21:17 PM

Перечисление доступа к члену позволяет получать значения из элементов коллекции, но не задавать значения элементов в коллекции. Например:

$files.LastWriteTime = (Get-Date).AddDays(-1)
InvalidOperation: The property 'LastWriteTime' cannot be found on this object.
Verify that the property exists and can be set.

Чтобы задать значения, необходимо использовать метод.

$files.set_LastWriteTime((Get-Date).AddDays(-1))
$files.LastWriteTime
Thursday, June 24, 2021 1:23:30 PM
Thursday, June 24, 2021 1:23:30 PM

Метод set_LastWriteTime() является скрытым членом объекта FileInfo. В следующем примере показано, как найти скрытые set методы.

$files | Get-Member -Force -Name set_*
   TypeName: System.IO.FileInfo

Name              MemberType Definition
----              ---------- ----------
Attributes        Property   System.IO.FileAttributes Attributes {get;set;}
CreationTime      Property   datetime CreationTime {get;set;}
CreationTimeUtc   Property   datetime CreationTimeUtc {get;set;}
IsReadOnly        Property   bool IsReadOnly {get;set;}
LastAccessTime    Property   datetime LastAccessTime {get;set;}
LastAccessTimeUtc Property   datetime LastAccessTimeUtc {get;set;}
LastWriteTime     Property   datetime LastWriteTime {get;set;}
LastWriteTimeUtc  Property   datetime LastWriteTimeUtc {get;set;}

Внимание

Так как метод выполняется для каждого элемента в коллекции, необходимо учитывать при вызове методов с помощью перечисления элементов.

См. также